LeetCode 144 ——二叉樹的前序遍歷
阿新 • • 發佈:2018-11-17
1. 題目
2. 解答
2.1. 遞迴法
定義一個存放樹中資料的向量 data,從根節點開始,如果節點不為空,那麼
-
- 將當前節點的數值加入到 data 中
-
- 遞迴得到其左子樹的資料向量 temp,將 temp 合併到 data 中去
-
- 遞迴得到其右子樹的資料向量 temp,將 temp 合併到 data 中去
/** * 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<int> preorderTraversal(TreeNode* root) { vector<int> data = {}; vector<int> temp = {}; if (root != NULL) { data.push_back(root->val); temp = preorderTraversal(root->left); data.insert(data.end(),temp.begin(),temp.end()); temp = preorderTraversal(root->right); data.insert(data.end(),temp.begin(),temp.end()); } return data; } };
2.2. 迭代法
定義一個存放樹中節點的棧 node_stack 和存放資料的向量 data,從根節點開始,如果節點不為空或者棧非空,迴圈以下過程:
-
- 如果節點非空,將節點的值加入 data,如果節點有右孩子,將節點右孩子壓入棧,節點指向其左孩子,迴圈直到節點為空
-
- 如果節點為空,棧非空,則彈出棧頂節點
/** * 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<int> preorderTraversal(TreeNode* root) { vector<int> data = {}; stack<TreeNode*> node_stack; TreeNode* temp = root; while (temp || !node_stack.empty()) { while(temp != NULL) { data.push_back(temp->val); if (temp->right) node_stack.push(temp->right); temp = temp->left; } // 若最後一個節點沒有右子節點,棧為空 if (!node_stack.empty()) // 棧非空 { temp = node_stack.top(); node_stack.pop(); } } return data; } };
2.3. Morris 遍歷法
前面兩種方法要麼需要函式棧要麼需要人工棧,其空間複雜度為 \(O(n)\),而 Morris 遍歷法可以做到在不影響時間複雜度的情況下做到空間複雜度為 \(O(1)\)。
定義一個存放資料的向量 data,從根節點開始,如果當前節點非空,迴圈以下過程:
-
- 如果當前節點沒有左孩子,將當前節點的值加入到 data 中,當前節點指向其右孩子
-
- 如果當前節點有左孩子,則尋找當前節點的前驅節點,即節點值小於該節點值並且值最大的節點,也即當前節點左子樹中值最大的節點
- a) 如果前驅節點沒有右孩子,前驅節點右孩子指向當前節點,將當前節點的值加入到 data 中,當前節點指向其左孩子
- b) 如果前驅節點右孩子為當前節點,當前節點指向其右孩子,前驅節點右孩子設為空(恢復原有樹結構)
/**
* 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<int> preorderTraversal(TreeNode* root) {
vector<int> data = {};
TreeNode* cur = root;
TreeNode* pre = NULL;
while (cur)
{
if (cur->left == NULL)
{
data.push_back(cur->val);
cur = cur->right;
}
else
{
// 尋找前驅結點
pre = cur->left;
while (pre->right != cur && pre->right)
{
pre = pre->right;
}
if (pre->right == NULL)
{
data.push_back(cur->val);
pre->right = cur;
cur = cur->left;
}
else
{
cur = cur->right;
pre->right = NULL;
}
}
}
return data;
}
};
獲取更多精彩,請關注「seniusen」!