题目

给定一个二叉树,检查它是否是镜像对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

1

/
2 2
/ \ /
3 4 4 3

但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:

1

/
2 2
\
3 3

进阶:
你可以运用递归和迭代两种方法解决这个问题吗?

思路一,超时

层序遍历,然后如果该结点是空结点,往该层子数组中填0,否则填val;
当此层所有结点都被遍历了(包括空结点),观察子数组是否对称。
然后更新queue,如果该结点为空结点,则它的子结点也是空结点,如果该结点不是空结点,它的子结点根据真实情况填,如果为空也填入NULL。
不过这样好像超时了,也就无法验证了。
退出循环的条件是,该层的所有结点都是空结点

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {public:bool isSymmetric(TreeNode* root) {queue<TreeNode*> que;if(root!=NULL) que.push(root);while(1){//该层结点元素个数 = 该层队列元素int size = que.size();vector<int> vec;int null_times=0;//这里要使用固定大小的size,不能使用que.size(),因为在处理中que.size是不断变化的//将这层元素送入队列中并依次从队首向队尾将元素出队列,每个元素出队列的同时又将其不为空的子结点送入队列for(int i =0;i<size;i++){TreeNode* node = que.front();//将队首元素送入该层结果que.pop();if(node!=NULL) {vec.push_back(node->val);//将左右孩子结点入队列,作为下一层的元素if(node->left!=NULL) que.push(node->left);else que.push(NULL);if(node->right!=NULL) que.push(node->right);else que.push(NULL);}else{null_times++;vec.push_back(-2147483648);//将左右孩子结点入队列,作为下一层的元素que.push(NULL);que.push(NULL);} }if(null_times == size) break;int vecsize=vec.size();for(int j=0;j<vecsize/2+1;j++){if(vec[j]!=vec[vecsize-1-j]) return false;}}return true;}
};

思路二,构造翻转二叉树,判断是否相同

先构造一棵反转二叉树,然后按顺序遍历这两棵树,判断是否相同。
Leetcode226. 翻转二叉树(递归、迭代、层序三种解法)
LeetCode 100. 相同的树 思考分析
不过此处有一个问题,我们当时翻转二叉树的操作是在输入的二叉树上进行修改的。这样如果直接isSameTree(root,invertTree(root));
得到的结果都是true。所以我们需要先深复制一个新的二叉树,然后在新的二叉树上完成翻转操作,然后将翻转后的二叉树与原本的二叉树进行判断。
关于深复制一棵二叉树:
LintCode 375. 克隆二叉树(深复制)

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {public:TreeNode* invertTree(TreeNode* root) {queue<TreeNode*> que;if(root!=NULL) que.push(root);while(!que.empty()){int size = que.size();for(int i =0;i<size;i++){TreeNode* node = que.front();que.pop();TreeNode* tmp;tmp = node->left;node->left = node->right;node->right = tmp;//将左右孩子结点入队列,作为下一层的元素if(node->left) que.push(node->left);if(node->right) que.push(node->right);}}return root;}bool isSameTree(TreeNode* p, TreeNode* q) {if(p && q){if(p->val == q->val){return isSameTree(p->right,q->right) && isSameTree(p->left,q->left);}else{return false;} }else if(!p && !q){return true;}return false;}TreeNode * preorder(TreeNode * root){if(root==NULL) return NULL;TreeNode * ans;ans=new TreeNode(root->val);if(root->left!=NULL){ans->left=preorder(root->left);}if(root->right!=NULL){ans->right=preorder(root->right);}return ans;}bool isSymmetric(TreeNode* root) {TreeNode *roota;roota=preorder(root);return isSameTree(root,invertTree(roota));}
};

参考其他思路

之前的构造的思路会导致空间严重浪费,并且时间耗费也较多。
关于二叉树是否对称,我们要比较的是根结点的左子树与右子树是不是相互翻转的。递归遍历的时候要同时遍历两棵树,比较两棵子树的里侧和外侧元素是否相同。
本题的遍历顺序为后序遍历,因为要通过递归函数的返回值来判断两个子树的内测结点与外侧结点是否相等。
一棵树遍历顺序为左右中,另一棵树遍历顺序是右左中。这里可以理解为一种回溯的思想。

递归法

1、确定递归地参数和返回值
参数:该结点的左子树结点、右子树结点
返回值:bool类型
bool compare(TreeNode* left,TreeNode* right)
2、确定终止条件
1、左右都为空,返回true
2、左右只有一个为空,返回false
3、左右结点均不为空,比较结点数值,不相同返回false
4、左右结点均不为空,数值相同返回true

if(left == NULL && right==NULL) return true;
else if(left!=NULL && right==NULL) return false;
else if(right!=NULL && left==NULL) return false;
else if(left->val != right->val) return false;

3、确定单层递归逻辑
处理左右结点皆不为空且数值相同的情况。
1、比较二叉树外侧是否对称:传入左结点的左孩子,右结点的右孩子。
2、比较内侧是否对称,传入左结点的右孩子,右结点的左孩子。
3、如果左右都对称就返回true,否则返回false

bool outside = compare(left->left,right->right);
bool inside = compare(left->right,right->left);
bool isSame = outside && inside;
return isSame

完整代码

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {public:bool compare(TreeNode* left,TreeNode* right){if(left == NULL && right==NULL) return true;else if(left!=NULL && right==NULL) return false;else if(right!=NULL && left==NULL) return false;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);}
};

迭代法

这一题的本质是判断两个树是否相互翻转,并非简单的遍历。这里可以使用队列来比较两个树(根结点的左右子树)是否相互翻转。

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
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;}//左右一个结点不为空,或者都不为空但是数值不同,返回falseif((!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;}
};

LeetCode 101. 对称二叉树 思考分析相关推荐

  1. leetcode 617. 合并二叉树 思考分析

    题目 给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠. 你需要将他们合并为一个新的二叉树.合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否 ...

  2. [leetcode] 101. 对称二叉树

    101. 对称二叉树 一开始想复杂了呀,没有做出来 直观的思路就是反转这颗树,然后判断两颗树是不是相同的 class Solution {// 反转并创建一颗树public TreeNode reve ...

  3. LeetCode 101 对称二叉树的几种思路(Python实现)

    对称二叉树 给定一个二叉树,检查它是否是镜像对称的. 例如,二叉树 [1,2,2,3,4,4,3] 是对称的. 1 / \ 2 2 / \ / \3 4 4 3 但是下面这个 [1,2,2,null, ...

  4. LeetCode 101对称二叉树

    力扣对称二叉树 思路: 1.递归 当根节点的左子树和右子树对称时,二叉树对称 根节点的左子树和右子树对称: 左子树的左子树和右子树的右子树相等 左子树的右子树和右子树的左子树相等 递归出口 (1)根节 ...

  5. LeetCode 101. 对称二叉树(递归循环)

    1. 题目 给定一个二叉树,检查它是否是镜像对称的. 例如,二叉树 [1,2,2,3,4,4,3] 是对称的.1/ \2 2/ \ / \ 3 4 4 3 但是下面这个 [1,2,2,null,3,n ...

  6. leetcode - 101. 对称二叉树

    给定一个二叉树,检查它是否是镜像对称的. 例如,二叉树 [1,2,2,3,4,4,3][1,2,2,3,4,4,3][1,2,2,3,4,4,3] 是对称的. 但是下面这个 [1,2,2,null,3 ...

  7. Leetcode 101.对称二叉树

    Time: 20190901 题目描述 给定一个二叉树,检查它是否是镜像对称的. 例如,二叉树 [1,2,2,3,4,4,3] 是对称的. 1/ \2 2/ \ / \ 3 4 4 3 但是下面这个 ...

  8. leetcode 101. 对称二叉树 递归解法 c语言

    如题: 给定一个二叉树,检查它是否是镜像对称的. 例如,二叉树 [1,2,2,3,4,4,3] 是对称的.1/ \2 2/ \ / \ 3 4 4 3但是下面这个 [1,2,2,null,3,null ...

  9. Leetcode 101.对称二叉树 (每日一题 20210709)

    给定一个二叉树,检查它是否是镜像对称的.例如,二叉树 [1,2,2,3,4,4,3] 是对称的.1/ \2 2/ \ / \ 3 4 4 3但是下面这个 [1,2,2,null,3,null,3] 则 ...

最新文章

  1. 遇到大容量磁盘你该怎么办?
  2. 中国最大AI芯片发布,顺手拿下四个国内第一,带Benchmark的那种
  3. 字段为NULL导致MyBatis在Oracle上执行SQL报错,无效的列类型
  4. 反浏览器指纹追踪(反浏览器指纹追踪技术)
  5. mysql 拼音查询_mysql实现用拼音搜索中文的数据库实现
  6. [02] JSP内置对象
  7. 【Java】第一阶段练习题
  8. Spring AOP自动创建代理 和 ProxyFactoryBean创建代理
  9. href up test.php,test.php
  10. 了解SQL Server审核
  11. 用cxf编写基于spring的webservice之上篇
  12. [翻译]NUnit---Explicit and Ignore Attributes(十二)
  13. C# winform程序运行在XP
  14. html table 表格
  15. html5效果案例,10个优秀HTML5网站案例赏析
  16. 制作flash动画心得
  17. 凸优化——对偶问题解题步骤
  18. 国产化复旦微电子 FMQL45T900 FPGA开发板( 替代Xilinx ZYNQ ARM+FPGA 7045开发板)
  19. 极坐标系及其他常用坐标系的表示方法
  20. java操控手机刷锦鲤看看(一个类似头条的赚钱app)

热门文章

  1. java实现儿时的超级玛丽游戏
  2. d3 mysql_javascript – 在d3可视化中访问MySQL数据库
  3. 干加个偏旁可以变成什么字_面试官:“干”字加一笔,变成什么字?回答王和午字不对...
  4. vue获取DOM元素并设置属性
  5. html基本标签与属性
  6. 反射与二次加工标准类型
  7. 结构化日志:出错时你最想要的好朋友
  8. scala akka通信机制
  9. CAlayer层的属性
  10. asp.net中,%#%,%=%和%%分别是什么意思,有什么区别