對稱的二叉樹

Waitt_發表於2018-12-19

劍指OFFER題21------按牛客網通過率排序

時間:2018.12.19.2048
作者:Waitt

題目

請實現一個函式,用來判斷一顆二叉樹是不是對稱的。注意,如果一個二叉樹同此二叉樹的映象是同樣的,定義其為對稱的。

時間限制:1秒 空間限制:32768K 熱度指數:111982

解答

思路1:

中序遍歷二叉樹,用向量儲存值(空結點用0代替),從前後遍歷向量,若有不相等的值,則說明為非對稱。

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    vector<int> a;//全域性向量存貯值
    void zhon(TreeNode* pRoot)//中序遍歷
    {
        if(!pRoot)
        {
            a.push_back(0);//空指標處補0
            return;
        }
        zhon(pRoot->left);
        a.push_back(pRoot->val);
        zhon(pRoot->right);
    }
    bool isSymmetrical(TreeNode* pRoot)
    {
        if(!pRoot)
            return 1;
        zhon(pRoot);//此處呼叫中序遍歷函式
        int i=0;
        int j=a.size()-1;
        while(i<j)
        {
            if(a[i]!=a[j])
                return 0;
            i++;
            j--;
        }
        return 1;
    }
};

存在問題:當二叉樹所有值均相等時,則該方法無效。

思路2

可以使用先序遍歷或者後序遍歷,此處以先序遍歷為例:
先用先序遍歷得到一種結果,再用先序遍歷的對稱遍歷再得到一種結果。(空指標處要進行填充處理)
只有兩種遍歷的結果相同,則說明此樹對稱。
先序遍歷:根、左、右。
先序遍歷的對稱:根、右、左。

利用額外兩個向量進行判斷:

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    vector<int> a,b;// a用來儲存先序遍歷的結果,b用來儲存先序遍歷對稱結果
    void xian(TreeNode* pRoot)//先序遍歷函式
    {
        if(!pRoot)
        {
            a.push_back(0);//空指標處補0
            return;
        }
        a.push_back(pRoot->val);
        xian(pRoot->left);
        xian(pRoot->right);
    }
    void xid(TreeNode* pRoot)//先序遍歷的對稱函式
    {
        if(!pRoot)
        {
            b.push_back(0);//空指標處補0
            return;
        }
        b.push_back(pRoot->val);
        xid(pRoot->right);
        xid(pRoot->left);
    }
    bool isSymmetrical(TreeNode* pRoot)
    {
        if(!pRoot)
            return 1;
        xian(pRoot);
        xid(pRoot);
        int i=0;
        if(a.size()!=b.size())
            return 0;
        for(int i=0;i<a.size();i++)
        {
            if(a[i]!=b[i])
                return 0;
        }
        return 1;
    }
};

不利用額外向量,逐個進行對比,利用同一個樹的兩個指標

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    bool fuzhu(TreeNode* pRoot1,TreeNode* pRoot2)//定義兩個指標引數
    {
        if(pRoot1==NULL && pRoot2==NULL)//均為空指標時,說明兩個結點相等
            return 1;
        if(pRoot1==NULL || pRoot2==NULL)//僅有一個空指標時,說明結點肯定不相等
            return 0;
        if(pRoot1->val!=pRoot2->val)//若兩個結點的值相等,則進行下一步判斷
            return 0;
        bool l=fuzhu(pRoot1->left,pRoot2->right);//一個結點向左,一個結點向右
        bool r=fuzhu(pRoot2->left,pRoot1->right);//與上一步對稱
        return l&&r;
    }
    bool isSymmetrical(TreeNode* pRoot)
    {
        if(!pRoot)
            return 1;
        return fuzhu(pRoot,pRoot);
    }

};

TIPS

廣度優先搜尋(BFS)與深度優先搜尋(DFS)
深度優先搜尋用棧(stack)來實現,整個過程可以想象成一個倒立的樹形:
1、把根節點壓入棧中。
2、每次從棧中彈出一個元素,搜尋所有在它下一級的元素,把這些元素壓入棧中。並把這個元素記為它下一級元素的前驅。
3、找到所要找的元素時結束程式。
4、如果遍歷整個樹還沒有找到,結束程式。

廣度優先搜尋使用佇列(queue)來實現,整個過程也可以看做一個倒立的樹形:
1、把根節點放到佇列的末尾。
2、每次從佇列的頭部取出一個元素,檢視這個元素所有的下一級元素,把它們放到佇列的末尾。並把這個元素記為它下一級元素的前驅。
3、找到所要找的元素時結束程式。
4、如果遍歷整個樹還沒有找到,結束程式。

相關文章