https://leetcode.cn/problems/symmetric-tree/
![](https://i-blog.csdnimg.cn/blog_migrate/507244e8a6b4cfe1facdea71d96f0996.png)
思路:
详细的解释可以参考卡哥的代码随想录(https://programmercarl.com/0101.%E5%AF%B9%E7%A7%B0%E4%BA%8C%E5%8F%89%E6%A0%91.html#%E9%80%92%E5%BD%92%E6%B3%95),写的非常详细,本文仅作为个人学习后针对自己思路的整理。
首先我们看到这道题目,想到如何去做?我们学习了三种遍历方法,递归迭代(栈)层序(队列),任何题目无非是在这三大类中去找寻思路,我们再去审题。
判断左右对称并不是左节点右节点,而是根节点的左右子树,节点的左右判断完后,要判断根节点的左右的子节点,详细的说也就是根节点的左节点的左节点(示例中的3)对比根节点的右节点的右节点(示例中的3),在对比根节点的右节点的左节点和根节点左节点的右节点(4),这个时候我们发现,我们想要判断每一层的这几个节点是否相等,但凡有不相等的就return false。这下就有思路了。
首先是递归,依然是确认递归三要素:
参数和返回值:题目要求返回true or false,所以我们使用bool,参数的话我们分别讨论左子树和右子树。
bool compareTree(TreeNode* left, TreeNode* right){
2 .终止条件:只有都为空的时候会停下,其余情况可以看上面的例子分析。
if(left != NULL && right == NULL) return false;
else if(left == NULL && right != NULL) return false;
else if(left == NULL && right == NULL) return true;
else if(left != NULL && right != NULL && left -> val != right -> val) return false;
3.单层递归逻辑:
此时才进入单层递归的逻辑,单层递归的逻辑就是处理 左右节点都不为空,且数值相同的情况。
比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。
比较内测是否对称,传入左节点的右孩子,右节点的左孩子。
如果左右都对称就返回true ,有一侧不对称就返回false 。
bool outside = compare(left->left, right->right); // 左子树:左、 右子树:右
bool inside = compare(left->right, right->left); // 左子树:右、 右子树:左
bool isSame = outside && inside; // 左子树:中、 右子树:中(逻辑处理)
return isSame;
整体代码如下:
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if (root == NULL) return true;
return compareTree(root->left, root->right);
}
bool compareTree(TreeNode* left, TreeNode* right){
if(left != NULL && right == NULL) return false;
else if(left == NULL && right != NULL) return false;
else if(left == NULL && right == NULL) return true;
else if(left != NULL && right != NULL && left -> val != right -> val) return false;
bool outside = compareTree(left -> left,right -> right);
bool inside = compareTree(left -> right,right -> left);
bool issame = outside && inside;
return issame;
}
};
同样的思路可以使用迭代法:
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;
}
// 左右一个节点不为空,或者都不为空但数值不相同,返回false
if ((!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;
}
};