寫在前面
這道題是在阿里面試時,手撕代碼的題目。剛開始用遞歸實現了,面試官進一步要求,能否用循環的形式實現。
- 遞歸實現時,遞歸結束的判斷條件冗餘(剛開始寫了兩個判斷條件,節點爲空的時候返回,節點爲葉子節點的時候返回,其實沒有必要對節點是葉子節點的時候進行判斷)
leetcode226. 翻轉二叉樹
翻轉一棵二叉樹。
示例:
輸入:
4
/ \
2 7
/ \ / \
1 3 6 9
輸出:
4
/ \
7 2
/ \ / \
9 6 3 1
備註:
這個問題是受到 Max Howell 的 原問題 啓發的 :
谷歌:我們90%的工程師使用您編寫的軟件(Homebrew),但是您卻無法在面試時在白板上寫出翻轉二叉樹這道題,這太糟糕了。
完整代碼
後序遍歷遞歸形式
/**
* 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:
TreeNode* invertTree(TreeNode* root) {
if(root == NULL)
return root;
TreeNode * Lnode = invertTree(root->left);
TreeNode * Rnode = invertTree(root->right);
root->left = Rnode;
root->right = Lnode;
return root;
}
};
非遞歸實現:中序遍歷形式
/**
* 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:
TreeNode* invertTree(TreeNode* root) {
if(root == NULL)
return root;
TreeNode* p = root;
stack<TreeNode*> st;
while(!st.empty() || p){
while(p){
st.push(p);
p = p->left;
}
p = st.top();
st.pop();
//交換
TreeNode * temp = p->right;
p->right = p->left;
p->left = temp;
p = p->right;
}
return root;
}
};
後續遍歷非遞歸形式實現:
注意:什麼時候節點出棧?只有當該節點的左右孩子交換完後,纔出棧
/**
* 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:
TreeNode* invertTree(TreeNode* root) {
if(root == NULL)
return root;
TreeNode* p = root, *pre;
stack<TreeNode*> st;
while(!st.empty() || p){
while(p){
st.push(p);
p = p->left;
}//p是最左面的節點
p = st.top();
if(p->right == NULL || p->right == pre){//右孩子爲空,右孩子已經交換完
TreeNode * temp = p->right;
p->right = p->left;
p->left = temp;
pre = p;
p = NULL;
st.pop();
}
else{
p = p->right;
pre = NULL;
}
}
return root;
}
};
先序遍歷非遞歸形式:
簡單來講:將訪問節點修改成交換節點的左右子樹
/**
* 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:
TreeNode* invertTree(TreeNode* root) {
if(root == NULL)
return root;
TreeNode* p = root, *pre;
stack<TreeNode*> st;
while(!st.empty() || p){
while(p){
st.push(p);
TreeNode * temp = p->right;
p->right = p->left;
p->left = temp;
p = p->left;
}//p是最左面的節點
p = st.top();
st.pop();
p = p->right;
}
return root;
}
};
總結:這道題的本質:將 二叉樹中先序、中序、後序遍歷二叉樹中訪問節點的代碼 改成 交換節點的左右子樹的代碼就OK。