LeetCode刷题笔记(Symmetric Tree)

刚又刷了一道难度适中的题目,下面就和大家分享一下经验。

题目如下:

Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).

For example, this binary tree [1,2,2,3,4,4,3] is symmetric:

    1
   / \
  2   2
 / \ / \
3  4 4  3
 

But the following [1,2,2,null,3,null,3] is not:

    1
   / \
  2   2
   \   \
   3    3
 

Note:
Bonus points if you could solve it both recursively and iteratively.

题意分析:

给定一个二叉树,请判断它是否镜像对称。你可以用递归法或者迭代法解决该问题。

方法一(递归法DFS) 

采用深度优先搜索DFS,首先将给定的二叉树分成左右两个子树,这样就可以把问题转换成比较两个二叉树是否镜像对称了,思路与“https://blog.csdn.net/Vensmallzeng/article/details/94960252”相似,只是在递归调用时需要将左右子树换个位,如果不镜像对称则返回false,否则镜像对称返回True。

解题代码如下:

class Solution{
public:
     bool isSymmetric(TreeNode* root){
         if (!root) return true;
         //将一个二叉树分成左右两个子树
         return isSymmetric(root->left, root->right);
     }
     //将左右两个子树分别看做一个二叉树,然后自定义一个函数判断是否镜像对称
     bool isSymmetric(TreeNode* left, TreeNode* right){
         if(!left && !right) return true;
         if((!left && right) || (left && !right) || (left->val != right->val)) return false;
         return isSymmetric(left->left, right->right) && isSymmetric(left-> right, right-> left);
     }
};

提交后的结果如下:

 

方法二(迭代法) 

新建两个队列q1、q2,首先判断root节点是否为空,如果为空则直接返回true,否则将root的左右两个子结点(root->left、root->right)分别存入两个队列,然后开始while循环,循环条件为两个队列都不为空。在while循环中,首先分别将两个队列中的队首元素取出来,如果两个元素都是空结点,那么直接continue跳过(因为有可能某个结点没有左子结点但是右子结点仍然存在)。紧接着,如果有一个元素为空,另一个元素不为空,那么此时已经不对称了直接返回false。若两个元素都存在,但是其值不同,此时也已经不对称了直接返回false。否则将root->left的左、右子结点排入q1,同时将root->right的右、左子结点排入q2。最后,由于循环结束后两个队列一定均为空,所以不必再去判断两个队列是否同时为空,其他情况比如一空一不空的直接在循环内部就返回false了,故当循环结束后直接返回true即可。

注:以下四句之前不应该加判断是否为空,因为对于“[1,2,2,null,3,null,3]”这个例子,如果排除了空的情况,队列中最终存的结果会导致误判。

q1.push(temp1->left);
q1.push(temp1->right);
q2.push(temp2->right);
q2.push(temp2->left);

解题代码如下:

class Solution{
public:
    bool isSymmetric(TreeNode* root){
        if(!root) return true;
        queue<TreeNode*> q1, q2;
        q1.push(root->left);
        q2.push(root->right);
        while(!q1.empty() && !q2.empty()){
            TreeNode* temp1 = q1.front();
            q1.pop();
            TreeNode* temp2 = q2.front();
            q2.pop();
            if(!temp1 && !temp2) continue;
            if((!temp1 && temp2) || (temp1 && !temp2) || (temp1->val != temp2->val)) return false;
            q1.push(temp1->left);
            q1.push(temp1->right);
            q2.push(temp2->right);
            q2.push(temp2->left);
        }
        return true;
    }
};

提交后的结果如下:

方法三(堆栈法DFS)

在“https://blog.csdn.net/Vensmallzeng/article/details/94960252”中方法二的基础上进行改进。

解题代码如下:

注:为了有利于后面比较size,所以需要加判断是否为空。

if(temp1->right) s1.push(temp1->right);
if(temp2->left)   s2.push(temp2->left);
//若两个二叉树的结构不同则返回false
if (s1.size() != s2.size()) return false;


if(temp1->left)   s1.push(temp1->left);
if(temp2->right) s2.push(temp2->right);
//若两个二叉树的结构不同则返回false
if (s1.size() != s2.size()) return false;

以下四句之前不应该加判断是否为空,因为对于“[1,2,2,null,3,null,3]”这个例子,如果排除了空的情况,队列中最终存的结果会导致误判。

class Solution{
public:
    bool isSymmetric(TreeNode* root){
        stack<TreeNode*> s1, s2;
        if (!root) return true;
        if(root-> left) s1.push(root-> left);
        if(root-> right) s2.push(root-> right);
        while ( !s1.empty() && !s2.empty() ){
            TreeNode* temp1 = s1.top();
            s1.pop();
            TreeNode* temp2 = s2.top();
            s2.pop();
            //若两个二叉树的对应节点值不同则返回false
            if (temp1->val != temp2-> val) return false;
            //在保存节点的左右子节点之前,判断左右子节点是否为空,有利于后面比较size        
            if(temp1->right) s1.push(temp1->right);
            if(temp2->left) s2.push(temp2->left);
            //若两个二叉树的结构不同则返回false
            if (s1.size() != s2.size()) return false;
            if(temp1->left) s1.push(temp1->left);
            if(temp2->right) s2.push(temp2->right);
            //若两个二叉树的结构不同则返回false
            if (s1.size() != s2.size()) return false;
        }
        return s1.size() == s2.size();
    }
};

提交后的结果如下:

 

 

 

日积月累,与君共进,增增小结,未完待续。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值