1.题目描述
给你一个二叉树的根节点 root , 检查它是否轴对称。
示例1:
输入:root = [1,2,2,3,4,4,3] 输出:true
示例2:
输入:root = [1,2,2,null,3,null,3] 输出:false
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/symmetric-tree
2.题目分析
尝试通过一个中序遍历进行解题,按照初步想法,经过中序遍历后的结果如果是对称的,那么就说明树是对称的,然而好像在这种例子下出了问题。似乎单纯的遍历会面临这种奇怪的问题,虽然或许可以通过添加节点来进行辅助判断,但是假设对于每个空节点都赋值-1 的话,那么似乎空节点有些多,还是继续先从递归入手。
2.1 递归分析
采用递归的话,我们还是试图对问题进行分解,首先对于一个待确定的根节点root,如果我们要判断它是否是一个对称数的话,首先要做的就是判断距离它最近的两个左右节点是否满足条件,如果这两个都不满足的话,那么就可以直接判断该树不是一个对称树。否则的话就继续对其左右子树进行判断。这似乎就是一个简单的递归思想。
2.1.1 递归形式
首先按照题目所给的函数格式来试图写递归的话会发现比较难处理左右子树的递的问题。所以考虑实现一个辅助递归功能compare ,为了方便起见,其参数应该是两个树,我们根据compare 判断这两棵树是否相等。因此确定递归形式为bool compare(TreeNode* left, TreeNode* right) 。
2.1.2 递归边界条件
对于一个函数的递归必须要明确的是什么时候停止执行。在本次判断中的停止条件应该是:可以确定这棵树不是一个对称树就直接返回false 跳出递归。下面列举边界条件
- 左子树右子树均为空——必然是一个对称树
- 左子树或者右子树只有一个为空——必然不对称
- 左右子树均不为空而且左右子树根节点值不相等——必然不对称
2.1.2 当前递归执行逻辑
在确定未遇到上述的递归边界条件时,单层的执行逻辑应该就是直接进行递的操作,也就是在下一层执行compare 函数。
2.2 迭代分析
可以通过对树的特定方式遍历来判断它们位置上对称的每一对节点是否具有对称关系,如下图所示。 按照上述图示;
- 首先根节点不为空,然后。判断根节点的左右子节点是否满足条件
- 若1成立,则继续,判断上述两个节点的最外侧(3和3)是否满足条件
- 若2成立,则继续判断1中两个节点的内侧节点(4和4)是否满足条件
对于上述过程的节点保存需要一个辅助结构,其实上述过程也是一个模拟递归的过程。此时我们的遍历过程是类似一个层次遍历的,从上到下进行判断。所以类似层次遍历使用一个队列来进行存储每次遇到的对称位置的节点对。每次队列中队首的两个元素就应该是位置上对称的两个元素。
3.题目解答
3.1 递归解法
bool compare(TreeNode* left, TreeNode* right){
if(left ==nullptr && right !=nullptr) return false;
else if(right == nullptr && left!= nullptr) return false;
else if(right == nullptr && right == nullptr) return true;
else if(right->val != left->val) return false;
else {
return compare(left->left,right->right)&&
compare(left->right,right->left);
}
}
bool isSymmetric(TreeNode* root) {
if(root == nullptr) return true;
return compare(root->left,root->right);
}
3.2 迭代
bool isSymmetric(TreeNode* root) {
if(root == nullptr) return true;
queue<TreeNode*> que;
que.push(root->left);
que.push(root->right);
while(!que.empty()){
TreeNode *lts = que.front();
que.pop();
TreeNode *rts = que.front();
que.pop();
if(!lts && !rts) continue;
if(!lts ||!rts) return false;
if(lts->val != rts->val) return false;
que.push(lts->left);
que.push(rts->right);
que.push(lts->right);
que.push(rts->left);
}
return true;
}
总结:递归到底该咋写?
|