整理自劍指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;
}
};