mysql递归查询所有上下节点_非递归打印二叉树的所有路径,保存父节点和孩子节点到底有啥差别...
題目解讀
題目要求輸出二叉樹的所有路徑(字符串形式),乍一看很簡單,不就是二叉樹的遍歷嘛!其實不然,首先,我們用非遞歸的方式(C++)解決這道題(遞歸在產品代碼中是不允許使用的,其次定位 bug 的時候非常困難)。這道題并非簡單的 dfs(深度優先搜索),需要點技巧。
題目描述
標準 dfs 遍歷輸出 - 每次輸出孩子節點
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector binaryTreePaths(TreeNode* root) {
if (root == nullptr) {
return {};
}
vector ans;
vector> allPath;
stack s;
vector path;
s.push(root);
path.push_back(root->val);
cout << path.back() << endl;
while (!s.empty()) {
TreeNode* curr = s.top();
s.pop();
if (curr->right != nullptr) {
path.push_back(curr->right->val);
s.push(curr->right);
cout << path.back() << endl;
}
if (curr->left != nullptr) {
path.push_back(curr->left->val);
s.push(curr->left);
cout << path.back() << endl;
}
}
return ans;
}
};
借助棧,上述代碼實現了最簡單的 dfs 遍歷,結果如下:
標準 dfs 輸出 - 每次輸出孩子節點
棧中之所以先添加右葉子節點,是為了保證最終路徑輸出順序從左往右。
標準 dfs 遍歷輸出 - 每次輸出父親節點
上述代碼實現了標準 dfs 遍歷,但顯然不能滿足題目要求,那該怎么處理呢?我們繼續往下看。
class Solution {
public:
vector binaryTreePaths(TreeNode* root) {
if (root == nullptr) {
return {};
}
vector ans;
vector> allPath;
stack s;
vector path;
s.push(root);
path.push_back(root->val);
// cout << path.back() << endl;
while (!s.empty()) {
TreeNode* curr = s.top();
cout << curr->val << endl;
s.pop();
if (curr->right != nullptr) {
path.push_back(curr->right->val);
s.push(curr->right);
// cout << path.back() << endl;
}
if (curr->left != nullptr) {
path.push_back(curr->left->val);
s.push(curr->left);
// cout << path.back() << endl;
}
}
return ans;
}
};
上述代碼中,我們打印棧頂每次彈出的元素,可以得到如下結果:
標準 dfs 輸出 - 每次輸出父節點
也就是說,每次只要某個節點的孩子節點都入棧了,該節點就可以不用考慮了。這個例子中,棧中初始節點是 1,然后加入其孩子節點 3、2,1 出棧;再加入節點 2 的孩子節點 5,2 出棧;以此類推??墒?#xff0c;這還無法得到題目要求的結果呀!不著急,我們離答案已經越來越近了。
二叉樹的所有路徑
通過觀察發現:每次從棧頂彈出的節點,如果它沒有孩子節點,那么這個節點就是葉子節點,而且遇到的第一個葉子節點也是最左邊的葉子節點。我們把每次從棧頂彈出的節點記錄下來,保存在 vector 中,那么遇到第一個葉子節點時,我們就得到最左邊的一條路徑(1->2->5).但是,接下來棧頂彈出的元素可是 3,想要得到一條完整的路徑,必須將 3 和 1->2 拼接?;蛘哒f,要知道 3 之前彈出了哪些元素,我們把 3 之前棧頂彈出的元素 和 3 拼接,再與 3 之后的路徑拼接起來,即可得到第二條路徑。如何實現這點是這道題的關鍵所在。很容易想到的一點是,在輸出的前一條路徑(vector)基礎上,不斷將尾部元素丟棄,那什么時候停止丟棄呢?顯然,丟棄直到第一條路徑的尾部元素的右孩子節點是 3 即可。所以,path 這個 vector 中就不能記錄節點的值了,而要記錄節點的地址,因為值不是唯一的,而地址是唯一的。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector binaryTreePaths(TreeNode* root) {
if (root == nullptr) {
return {};
}
vector ans;
stack s;
vector path;
s.push(root);
string tmp;
while (!s.empty()) {
TreeNode* curr = s.top();
s.pop();
path.push_back(curr);
if (curr->right != nullptr) {
s.push(curr->right);
}
if (curr->left != nullptr) {
s.push(curr->left);
}
if (curr->left == nullptr && curr->right == nullptr) {
for (auto node : path) {
tmp += to_string(node->val);
if (node != path.back()) {
tmp += "->";
}
}
ans.push_back(tmp);
tmp.clear();
while (path.empty() == false && s.empty() == false && path.back()->right != s.top()) {
path.pop_back();
}
}
}
return ans;
}
};
這一次,終于得到了我們想要的結果了。上述代碼中記錄 string 的過程可以有更有效的方法,這里為了使代碼的呈現更加容易理解,就不處理了,讀者可以自己去研究下。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的mysql递归查询所有上下节点_非递归打印二叉树的所有路径,保存父节点和孩子节点到底有啥差别...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python如果选择不在列表里_Pyth
- 下一篇: nginx配置多个server_Ngin