剑指offer28.对称的二叉树

题目:101. 对称二叉树 - 力扣(LeetCode)

题目要求:给你一个二叉树的根节点 root , 检查它是否轴对称。

例如:

输入:root = [1,2,2,3,4,4,3]
输出:true

解题思路:

【一种错误的想法】

有一种方法是把二叉树顺序遍历一遍,再逆序遍历一遍,有什么方法能体现遍历是父节点、左子树、右子树的顺序呢?

——答案是中序遍历,中序遍历会访问先左子树 再父节点 后右子树。

于是,是不是可以先顺序中序遍历一遍,在逆序地中序遍历一遍(就是遍历的时候先访问右子树再访问左子树),然后比较两种遍历对应元素的值是否一样。这样顺序中序遍历的结果是[3, 2, 4, 1, 4, 2, 3],逆序遍历的结果是[3, 2, 4, 1, 4, 2, 3],一对比,结果一样,于是判断对称。

——但是,这个方法其实不行!

反例:

这样的话,循序终须中序遍历和逆序中序遍历的结果都是[2, 2, 1, 2, 2]

这种方法的错误之处在于只是用数值来比较对称性,没有用到位置信息(中序遍历体现了顺序信息,而没有很好地体现位置信息,所以还是不行)。

【正确的想法】

递归地判断二叉树对称位置上的元素是不是相等。

思路:对于每个节点,判断是否对称,就是比较左子树的右子树和右子树的左子树是否对称、左子树的左子树和右子树的右子树是否对称。

bool compare(TreeNode* left_root, TreeNode* right_root){
        return compare(left_root->left, right_root->right) && compare(left_root->right, right_root->left); 
}

当然,还有递归结束条件:

(1)左子树和右子树为空,说明对称,返回true

(2)左子树或右子树为空,说明不对称,返回false

(3)左子树和右子树都不是空的,比较数值,如果数值相等,继续递归,如果数值不相等,说明不对称,返回false。

代码:

/**
 * 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 compare(TreeNode* left_root, TreeNode* right_root){
        if(left_root==nullptr && right_root == nullptr) return true;
        if(left_root==nullptr || right_root == nullptr) return false;
        if(left_root->val != right_root->val) return false;
        return compare(left_root->left, right_root->right) && compare(left_root->right, right_root->left); 
    }
    bool isSymmetric(TreeNode* root) {
        if(root == nullptr) return true;
        return compare(root->left, root->right);
    }
};

时间复杂度分析:遍历了整棵树(或者说是遍历了整棵树的半边,另外半边是同步遍历的),时间复杂度为O(N);空间复杂度:最坏的情况是二叉树退化为链表,栈的深度为N(准确的说是\lceil N/2 \rceil),复杂度为O(N)。

有什么问题欢迎与我交流~

  • 13
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值