题目描述:
给你一个二叉树的根节点 root , 检查它是否轴对称。
示例 1:
输入:root = [1,2,2,3,4,4,3]
输出:true
示例 2:
输入:root = [1,2,2,null,3,null,3]
输出:false提示:
树中节点数目在范围 [1, 1000] 内
-100 <= Node.val <= 100
进阶:你可以运用递归和迭代两种方法解决这个问题吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/symmetric-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
分析:
这道题看提示有两种做法,然而我一种都不会。。。二叉树的递归一直是弱点。
一、迭代
这是层序遍历的变种,整体上按照层来压入新节点,从头部取出了老节点。
队列跟层序遍历有关,栈跟前序遍历和中序遍历有关
迭代看了看题解,大致知道是什么样的流程了。核心就是用队列来将递归函数转化为迭代算法。判断树是否为镜像对称:
1.树的左右节点入队列
2.队列不为空时,取出队列前两个节点
3.比较两个节点,两节点不相等返回false。
4.两节点相等,比较他们的左右节点按照相反的顺序入队列
5.重复执行2-5,直到队列为空或者返回了false
6.队列为空,说明该树是镜像对称,返回true
题解如下:
https://leetcode-cn.com/problems/symmetric-tree/solution/dui-cheng-er-cha-shu-by-leetcode-solution/
代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
// 递归算法转为迭代算法,常见的方法就是使用队列进行转换
queue q;
bool isSymmetric(TreeNode* root) {
// 树为空直接返回false
if(root==NULL) return false;
// 树的左右节点添加到队列中
q.push(root->left);
q.push(root->right);
// 进行判断
return f();
}
// f函数用来判断根节点的子树是否为镜像
bool f()
{
// l和r分别用来存储队列中两个相邻的节点
TreeNode *l=NULL;
TreeNode *r=NULL;
// 队列不为空,进行循环
while(!q.empty())
{
// 如果队列不为空,取出队列首节点,赋给l,之后删除该节点
if(!q.empty())
{
l=q.front();
q.pop();
}
// 如果队列不为空,取出队列首节点,赋给r,之后删除该节点
if(!q.empty())
{
r=q.front();
q.pop();
}
// 如果l和r为NULL,说明是镜像,进行下一次循环
if(!l&&!r) continue;
// 如果l和r只有一个为NULL,则说明不是镜像,返回false
if(!l||!r) return false;
// 如果l和r不相等,说明不是镜像,返回false
if(l->val!=r->val) return false;
else
{
// 如果l和r相等,说明截止到目前为止,该树还是镜像对称的
// 接下来判断l和r节点的左右子树
// l的左子树和r的右子树对称,因此加入队列
q.push(l->left);
q.push(r->right);
// l的右子树和r的左子树对称,因此加入队列
q.push(l->right);
q.push(r->left);
}
}
// 队列为空,说明遍历完整个树,没有发现不对称的情况,因此返回true
return true;
}
};
二、递归
递归不单单只有前序,中序和后序,还有很多的变种,要明白递归函数是干什么用的,它的功能是什么。比如这道题,如果定义递归函数f的功能为:判断左/右子树是否为镜像对称。那么就无法继续进行下去,因为左右子树镜像对称,并不能说明这两个子树相互镜像对称。例如,二叉树序列1,2,2,3,3,4,4,左子树2,3,3是镜像对称,右子树2,4,4也是镜像对称,但是左右子树并不镜像对称。
因此,必须改变函数f的功能。f的功能为先判断两节点是否镜像对称,再通过递归函数判断两个节点的左右子节点是否镜像对称。如果两个节点的左右子节点也镜像对称,则该二叉树镜像对称。
代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool isSymmetric(TreeNode* root) {
// 判断root的左右节点是否对称
return f(root->left,root->right);
}
// 函数f,用来判断两个节点是否为镜像对称
bool f(TreeNode* left,TreeNode* right)
{
// 两节点为NULL,镜像对称,返回true
if(!left&&!right) return true;
// 其中一个为NULL,不镜像对称,返回false
if(!left||!right) return false;
// 两节点不相等,不镜像对称,返回false
if(left->val!=right->val) return false;
// 两节点镜像对称,起决定作用的,只剩下两节点的左右节点是否镜像对称,如果也对称,则返回true
return f(left->left,right->right)&&f(left->right,right->left);
}
};