leetcode226. 翻轉二叉樹

寫在前面

這道題是在阿里面試時,手撕代碼的題目。剛開始用遞歸實現了,面試官進一步要求,能否用循環的形式實現。

  • 遞歸實現時,遞歸結束的判斷條件冗餘(剛開始寫了兩個判斷條件,節點爲空的時候返回,節點爲葉子節點的時候返回,其實沒有必要對節點是葉子節點的時候進行判斷)

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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章