日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[LeetCode] Binary Tree Postorder Traversal 二叉树的后序遍历

發(fā)布時間:2025/5/22 编程问答 66 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [LeetCode] Binary Tree Postorder Traversal 二叉树的后序遍历 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?

Given a binary tree, return the postorder traversal of its nodes' values.

For example:
Given binary tree {1,#,2,3},

1\2/3

return [3,2,1].

Note: Recursive solution is trivial, could you do it iteratively?

?

經(jīng)典題目,求二叉樹的后序遍歷的非遞歸方法,跟前序,中序,層序一樣都需要用到棧,后續(xù)的順序是左-右-根,所以當一個節(jié)點值被取出來時,它的左右子節(jié)點要么不存在,要么已經(jīng)被訪問過了。我們先將根結點壓入棧,然后定義一個輔助結點head,while循環(huán)的條件是棧不為空,在循環(huán)中,首先將棧頂結點t取出來,如果棧頂結點沒有左右子結點,或者其左子結點是head,或者其右子結點是head的情況下。我們將棧頂結點值加入結果res中,并將棧頂元素移出棧,然后將head指向棧頂元素;否則的話就看如果右子結點不為空,將其加入棧,再看左子結點不為空的話,就加入棧,注意這里先右后左的順序是因為棧的后入先出的特點,可以使得左子結點先被處理。下面來看為什么是這三個條件呢,首先如果棧頂元素如果沒有左右子結點的話,說明其是葉結點,而且我們的入棧順序保證了左子結點先被處理,所以此時的結點值就可以直接加入結果res了,然后移出棧,將head指向這個葉結點,這樣的話head每次就是指向前一個處理過并且加入結果res的結點,那么如果棧頂結點的左子結點或者右子結點是head的話,說明其子結點已經(jīng)加入結果res了,那么就可以處理當前結點了。

看到這里,大家可能對head的作用,以及為何要初始化為root,還不是很清楚,這里再解釋一下。head是指向上一個被遍歷完成的結點,由于后序遍歷的順序是左-右-根,所以一定會一直將結點壓入棧,一直到把最左子結點(或是最左子結點的最右子結點)壓入棧后,開始進行處理。一旦開始處理了,head就會被重新賦值。所以head初始化值并沒有太大的影響,唯一要注意的是不能初始化為空,因為我們在判斷是否打印出當前結點時除了判斷是否是葉結點,還要看head是否指向其左右子結點,如果head指向左子結點,那么右子結點一定為空,因為我們的入棧順序是根-右-左,不存在右子結點還沒處理,就直接去處理根結點了的情況。若head指向右子結點,則是正常的左-右-根的處理順序。那么回過頭來在看,若head初始化為空,且此時正好左子結點不存在,那么在壓入根結點時,head和左子結點相等就成立了,此時就直接打印根結點了,明顯是錯的。所以head只要不初始化為空,一切都好說,甚至可以新建一個結點也沒問題。將head初始化為root,也可以,就算只有一個root結點,那么在判定葉結點時就將root打印了,然后就跳出while循環(huán)了,也不會出錯。代碼如下:

?

解法一:

class Solution { public:vector<int> postorderTraversal(TreeNode* root) {if (!root) return {};vector<int> res;stack<TreeNode*> s{{root}};TreeNode *head = root;while (!s.empty()) {TreeNode *t = s.top();if ((!t->left && !t->right) || t->left == head || t->right == head) {res.push_back(t->val);s.pop();head = t;} else {if (t->right) s.push(t->right);if (t->left) s.push(t->left);}}return res;} };

?

由于后序遍歷的順序是左-右-根,而先序遍歷的順序是根-左-右,二者其實還是很相近的,我們可以先在先序遍歷的方法上做些小改動,使其遍歷順序變?yōu)楦?右-左,然后翻轉一下,就是左-右-根啦,翻轉的方法我們使用反向Q,哦不,是反向加入結果res,每次都在結果res的開頭加入結點值,而改變先序遍歷的順序就只要該遍歷一下入棧順序,先左后右,這樣出棧處理的時候就是先右后左啦,參見代碼如下:

?

解法二:

class Solution { public:vector<int> postorderTraversal(TreeNode* root) {if (!root) return {};vector<int> res;stack<TreeNode*> s{{root}};while (!s.empty()) {TreeNode *t = s.top(); s.pop();res.insert(res.begin(), t->val);if (t->left) s.push(t->left);if (t->right) s.push(t->right);}return res;} };

?

那么在Binary Tree Preorder Traversal中的解法二也可以改動一下變成后序遍歷,改動的思路跟上面的解法一樣,都是先將先序遍歷的根-左-右順序變?yōu)楦?右-左,再翻轉變?yōu)楹笮虮闅v的左-右-根,翻轉還是改變結果res的加入順序,然后把更新輔助結點p的左右順序換一下即可,代碼如下:

?

解法三:

class Solution { public:vector<int> postorderTraversal(TreeNode* root) {vector<int> res;stack<TreeNode*> s;TreeNode *p = root;while (!s.empty() || p) {if (p) {s.push(p);res.insert(res.begin(), p->val);p = p->right;} else {TreeNode *t = s.top(); s.pop();p = t->left;}}return res;} };

?

論壇上還有一種雙棧的解法,其實本質上跟解法二沒什么區(qū)別,都是利用了改變先序遍歷的順序來實現(xiàn)后序遍歷的,參見代碼如下:

?

解法四:

class Solution { public:vector<int> postorderTraversal(TreeNode* root) {if (!root) return {};vector<int> res;stack<TreeNode*> s1, s2;s1.push(root);while (!s1.empty()) {TreeNode *t = s1.top(); s1.pop();s2.push(t);if (t->left) s1.push(t->left);if (t->right) s1.push(t->right);}while (!s2.empty()) {res.push_back(s2.top()->val); s2.pop();}return res;} };

?

類似題目:

Binary Tree Preorder Traversal

Binary Tree Inorder Traversal

Binary Tree Level Order Traversal

?

參考資料:

https://leetcode.com/problems/binary-tree-postorder-traversal/

https://leetcode.com/problems/binary-tree-postorder-traversal/discuss/45803/java-solution-using-two-stacks

https://leetcode.com/problems/binary-tree-postorder-traversal/discuss/45551/preorder-inorder-and-postorder-iteratively-summarization

https://leetcode.com/problems/binary-tree-postorder-traversal/discuss/45621/preorder-inorder-and-postorder-traversal-iterative-java-solution

?

LeetCode All in One 題目講解匯總(持續(xù)更新中...)

總結

以上是生活随笔為你收集整理的[LeetCode] Binary Tree Postorder Traversal 二叉树的后序遍历的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。