【劍指Offer】面試題59:對稱二叉樹

整理自劍指Offer

一:題目描述


請實現一個函數,用來判斷一顆二叉樹是不是對稱的。注意,如果一個二叉樹同此二叉樹的鏡像是同樣的,定義其爲對稱的。


二:解題思路


看到這個題第一反應是求二叉樹的鏡像二叉樹,然後同時遍歷兩個樹,進行比較

遇到問題 :在求二叉樹的鏡像二叉樹改變了原始的二叉樹的結構,不可行


劍指Offer的解法:

如上圖,我們可以看出第一個二叉樹是對稱的,第二棵與第三棵是不對稱的


對樹的遍歷有三種方式:前序遍歷,中序遍歷,後序遍歷,在這三種方法中都是先遍歷左子結點再遍歷右子節點。

是否可以定義一種新的遍歷方式,先遍歷右子節點再遍歷左子結點


如先序遍歷:父結點,左子結點,右子節點

定義的基於先序遍歷的新的遍歷方式:父結點,右子節點,左子結點

如果兩者輸出的結果相同,則說明這個二叉樹是對稱的


如上圖第一棵樹:

先序遍歷 8、6、5、7、6、7、5

新的遍歷8、6、5、7、6、7、5

對稱

第二棵樹:

先序遍歷:8、6、5、7、9、7、5

新的遍歷:8、9、5、7、6、7、5

不對稱

第三棵樹

先序遍歷:7、7、7、7、7、7

新的遍歷:7、7、7、7、7、7

對稱?不對


如何解決這個問題:將葉子節點的NULL加入其中就可以解決


第三棵樹:

先序遍歷:7、7、7、NULL、NULL、7、NULL、NULL、7、7、NULL、NULL、NULL

新的遍歷:7、7、NULL、7、NULL、NULL、7、NULL、NULL、7、NULL、NULL

不對稱



三:代碼實現

遞歸版代碼

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    
    bool isSymmetricalCore(TreeNode* pRoot1,TreeNode* pRoot2){
        
        if(pRoot1==NULL && pRoot2==NULL)
            return true;
        if(pRoot1==NULL || pRoot2==NULL)
            return false;
        if(pRoot1->val!=pRoot2->val)
            return false;
        //階梯思想容易理解,但是遞歸的代碼不易理解
        //可以將pRoot1看成是先序遍歷的指針,先左後右
        //可以將pRoot2看成是新的遍歷的指針,先右後左
        //如果兩者相同,比較下一個對稱位置的結點
        //如果不相等,返回false
        return isSymmetricalCore(pRoot1->left,pRoot2->right)&&
            isSymmetricalCore(pRoot1->right,pRoot2->left);
    }
    
    bool isSymmetrical(TreeNode* pRoot)
    {
        //遞歸版本
    
        //根節點爲空指針,認爲是對稱的
        if(pRoot==NULL)
            return true;
 		return isSymmetricalCore(pRoot,pRoot);
   }

};

非遞歸版代碼--隊列方式實現

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    bool isSymmetrical(TreeNode* pRoot)
    {
      
        if(pRoot==NULL)
            return true;
        //利用兩個隊列保存兩種遍歷的結果,隊列先進先出
        //q1:先序遍歷結果  q2:新的遍歷的結果
        queue<TreeNode*>q1,q2;
        TreeNode *left,*right;
        //入隊
        q1.push(pRoot->left); //先左後右
        q2.push(pRoot->right); //先右後左
        while(!q1.empty() && !q2.empty()){
            
            left=q1.front();  //取隊首元素
            q1.pop();   //出隊
            right=q2.front();
            q2.pop();
            
            //對稱位置均空,繼續
            if(left==NULL && right==NULL)
                continue;
            //對稱位置一空一不空,不對稱
            if(left==NULL || right==NULL)
                return false;
            //對稱位置值不相同,不對稱
            if(left->val!=right->val)
                return false;
            
            q1.push(left->left);
            q1.push(left->right);
            q2.push(right->right);
            q2.push(right->left);
            
        }
        return true;
    }
};


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