lc[二叉树]---101.对称二叉树

一、题目描述

 个人的ac代码:(层序遍历,对称的去看):

注:如何删除vector的第一个值

auto iter=que.begin();
iter=que.erase(iter);
class Solution 
{
public:
    bool isSymmetric(TreeNode* root) 
    {
        TreeNode* p;bool flag=true;
        if(root==nullptr)return true;
        vector<TreeNode*>que;
        que.push_back(root);
        while(!que.empty()&&flag)
        {
            int cnt=que.size();
            int i=0,j=cnt-1;
            while(i<=j)
            {
                if(que[i]->left)//如果i指针有左孩子,那么j有同等的右孩子
                    if(que[j]->right==nullptr||que[i]->left->val!=que[j]->right->val)
                        {flag=false;break;}
                if(que[i]->right)//如果i指针有右孩子,那么j有同等的左孩子
                    if(que[j]->left==nullptr||que[i]->right->val!=que[j]->left->val)
                        {flag=false;break;}
                if(que[j]->left)//j指针有左孩子,i同等的右孩子(反向判断一下,否则部分样例进不来)
                    if(que[i]->right==nullptr||que[j]->left->val!=que[i]->right->val)
                        {flag=false;break;}
                if(que[j]->right)//j指针有右孩子,那么i有同等的左孩子
                    if(que[i]->left==nullptr||que[j]->right->val!=que[i]->left->val)
                        {flag=false;break;}
                i++;j--;
            }
            for(int i=0;i<cnt;i++)
            {
                auto iter=que.begin();
                p=que[0];iter=que.erase(iter);

                if(p->left)     que.push_back(p->left);
                if(p->right)    que.push_back(p->right);
            }//完成本层的结点的读取
        }
        return flag;
    }
};

二、参考思路与代码:

感悟:二叉树类的题目一定要优先确定好利用什么样的遍历顺序

1.递归法:101. 对称二叉树1

        本题遍历只能是“后序遍历”,因为我们要通过递归函数的返回值来判断两个子树的内侧节点和外侧节点是否相等。

        正是因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中。

        但都可以理解算是后序遍历,尽管已经不是严格上在一个树上进行遍历的后序遍历了。

其实后序也可以理解为是一种回溯,当然这是题外话,讲回溯的时候会重点讲的。

递归三部曲:

 C++完整代码:

class Solution {
public:
    bool compare(TreeNode* left, TreeNode* right) {
        // 首先排除空节点的情况
        if (left == NULL && right != NULL) return false;
        else if (left != NULL && right == NULL) return false;
        else if (left == NULL && right == NULL) return true;
        // 排除了空节点,再排除数值不相同的情况
        else if (left->val != right->val) return false;

        // 此时就是:左右节点都不为空,且数值相同的情况
        // 此时才做递归,做下一层的判断
        bool outside = compare(left->left, right->right);   // 左子树:左、 右子树:右
        bool inside = compare(left->right, right->left);    // 左子树:右、 右子树:左
        bool isSame = outside && inside;                    // 左子树:中、 右子树:中 (逻辑处理)
        return isSame;

    }
    bool isSymmetric(TreeNode* root) {
        if (root == NULL) return true;
        return compare(root->left, root->right);
    }
};

2.迭代法

        要注意,这里的迭代法可不是前中后序的迭代写法,因为本题的本质是判断两个树是否是相互翻转的,其实已经不是所谓二叉树遍历的前中后序的关系了。可以使用队列来比较两个树(根节点的左右子树)是否相互翻转,(注意这不是层序遍历

        ①队列(成对的比较)

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if (root == NULL) return true;
        queue<TreeNode*> que;
        que.push(root->left);   // 将左子树头结点加入队列
        que.push(root->right);  // 将右子树头结点加入队列
        
        while (!que.empty()) {  // 接下来就要判断这两个树是否相互翻转
            TreeNode* leftNode = que.front(); que.pop();
            TreeNode* rightNode = que.front(); que.pop();
            if (!leftNode && !rightNode) {  // 左节点为空、右节点为空,此时说明是对称的
                continue;
            }

            // 左右一个节点不为空,或者都不为空但数值不相同,返回false
            if ((!leftNode || !rightNode || (leftNode->val != rightNode->val))) {
                return false;
            }
            que.push(leftNode->left);   // 加入左节点左孩子
            que.push(rightNode->right); // 加入右节点右孩子
            que.push(leftNode->right);  // 加入左节点右孩子
            que.push(rightNode->left);  // 加入右节点左孩子
        }
        return true;
    }
};

        ②栈

这个迭代法,其实是把左右两个子树要比较的元素顺序放进一个容器,然后成对成对的取出来进行比较,那么其实使用栈也是可以的。

只要把队列原封不动的改成栈就可以了,我下面也给出了代码。

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if (root == NULL) return true;
        stack<TreeNode*> st; // 这里改成了栈
        st.push(root->left);
        st.push(root->right);
        while (!st.empty()) {
            TreeNode* leftNode = st.top(); st.pop();
            TreeNode* rightNode = st.top(); st.pop();
            if (!leftNode && !rightNode) {
                continue;
            }
            if ((!leftNode || !rightNode || (leftNode->val != rightNode->val))) {
                return false;
            }
            st.push(leftNode->left);
            st.push(rightNode->right);
            st.push(leftNode->right);
            st.push(rightNode->left);
        }
        return true;
    }
};

三、相关题目推荐:

这两道题目基本和本题是一样的,只要稍加修改就可以AC。

  • 100.相同的树
  • 572.另一个树的子树
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Ocean__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值