LeetCode [101] 对称二叉树

本文介绍了如何使用递归深度优先搜索(DFS)和广度优先搜索(BFS)判断一棵二叉树是否对称。在DFS方法中,主要比较左右子树的对应节点;在BFS方法中,通过队列逐层对比节点。两种方法都涉及到对二叉树结构的理解和有效遍历。
摘要由CSDN通过智能技术生成

对称二叉树

好久没有刷力扣了,看看之前刷过的题目,再做一遍有新感觉

首先要搞清楚题目意思,不要一上来就下手做,发现规律,找准切入点,编码还是很快的。

对称二叉树是要求树成轴对称(并不是左右子树相同,因为刚做了相同二叉树的题目,先入为主,导致认为需要左右子树相同)

第一种解法-递归 DFS

一般树的问题可以考虑递归,以根节点为例,如果左右子树为空,则以本节点为根的树是对称二叉树,返回True;如果左右子树有一个节点为空,则返回False;如果左右子树都不为空且值相等,则继续迭代下一层,继续查看左子树的左子树与右子树的右子树  左子树的右子树与右子树的左子树;如果左右子树的值不等,直接返回False.代码如下:

bool isSymmetric(TreeNode* root) {
        if(root == nullptr) return true;
        return dfs(root->left, dfs->right);
    }
bool dfs(TreeNode* left, TreeNode* right)
{
    if(left == nullptr && right == nullptr) return true;
    if(left == nullptr || right == nullptr) return false;
    return (left->val == right->val) && 
            dfs(left->left, right->right) &&
            dfs(left->right, right->left);
}

第二种解法-层序遍历 BFS

层序是一种比较直观的做法,如果为对称二叉树,则每一层遍历出来的值是一个对称数组。每次都把应该对称的左右子节点先后放进queue中,判断的时候每次取出前两个(每次都取queue的front(),连续取两次),判断之后,再把left->left与right->right   left->right与right->left放进去queue中。直到queue为空停止。代码如下:

bool isSymmetric(TreeNode* root) {
        //首先对根节点有一个基本的判断
        if(root->left == nullptr || root->right == nullptr)
            return root->left == root->right;
        if(root->left->val != root->right->val) return false;
        queue<TreeNode*> q;
        //把左右子树放进队列中
        q.push(root->left);
        q.push(root->right);
        while(!q.empty())
        {
            //这地方完全没必要判断,每次放到队列中都是成对
            //如果不是成对,已经在加入前返回了
            //if(q.size() % 2) return false;
            
            //每次取最前边queue.front(),pop()一次,再取,再pop()
            TreeNode* left = q.front();
            q.pop();
            TreeNode* right = q.front();
            q.pop();
            
            //left->left 与 right->right的判断
            if(left->left && right->right)
            {
                if(left->left->val != right->right->val) return false;
                q.push(left->left);
                q.push(right->right);
            }
            // 其中一个为空,另一个不为空,必false
            else if((left->left == nullptr && right->right != nullptr)
                || (left->left != nullptr && right->right == nullptr))
                return false;
            //left->right 与 right->left 的判断
            if(left->right && right->left)
            {
                if(left->right->val != right->left->val) return false;
                q.push(left->right);
                q.push(right->left);
            }
            // 其中一个为空,另一个不为空,必false
            else if((left->right == nullptr && right->left != nullptr)
                || (left->right != nullptr && right->left == nullptr))
                return false;
        }
        return true;
    }

一年前的BFS解法

冗余内容较多,代码重构还是蛮有意思的事情

  • 首先就是在每次遍历queue的地方,查看size()是否为2的倍数,这个地方比较多余
  • 其次是对queue的内容是真正的按层是遍历判断的,其实没有必要,每次都是紧挨着自动塞进队列两个需要比对的节点,可以减少对queue.size()的判断。
bool isSymmetric(TreeNode* root) {
        if(root == nullptr)
            return true;
        if(root->left == nullptr || root->right == nullptr)
            return root->left == root->right;
        if(root->left->val != root->right->val)
            return false;
        queue<TreeNode*> q;
        q.push(root->left);
        q.push(root->right);
        while(!q.empty())
        {
            int size = q.size();
            if(size % 2 != 0)
                return false;
            while(size > 0)
            {
                TreeNode* left = q.front();
                q.pop();
                TreeNode* right = q.front();
                q.pop();

                if(left->left != nullptr || right->right != nullptr)
                {
                    if(left->left == nullptr || right->right == nullptr)
                        return false;
                    if(left->left->val != right->right->val)
                        return false;
                }
                if(left->left && right->right)
                {
                    q.push(left->left);
                    q.push(right->right);
                }
                
                if(left->right != nullptr || right->left != nullptr)
                {
                    if(left->right == nullptr || right->left == nullptr)
                        return false;
                    if(left->right->val != right->left->val)
                        return false;
                }
                if(left->right && right->left)
                {
                    q.push(left->right);
                    q.push(right->left);
                }
                size -= 2;
            }
        }
        return true;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值