101. 对称二叉树

101. 对称二叉树

题目链接: 101. 对称二叉树(简单)

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

例如,二叉树 [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

进阶:

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

题解

思路:根据题意可知,判断一棵树是不是镜像对称的,就是对比根节点的“左子树”和“右子树”,镜像对称就是要求“左子树翻转以后和右子树一模一样”。对左子树可以采取左右中的遍历方式,而对右子树采取右左中的遍历方式。

代码(C++):

//方法一:递归(1.确定递归函数的参数和返回值;2.确定终止条件;3.确定单层递归的逻辑)
class Solution1 {
public:
    bool isSymmetric(TreeNode* root) {
        if (root == nullptr) return true;
        return compare(root->left, root->right);
    }
​
    bool compare(TreeNode* node1, TreeNode* node2) {
        if (node1 == nullptr && node2 != nullptr) return false;
        else if (node1 != nullptr && node2 == nullptr) return false;
        else if (node1 == nullptr && node2 == nullptr) return true;
        else if (node1->val != node2->val) return false;
        else if (node1->val == node2->val) {//其实这里的if语句写不写都可,因为前面把“这种情况”以外的所有情况都列举出来了
            bool result1 = compare(node1->left, node2->right);//左子树:左;右子树:右
            bool result2 = compare(node1->right, node2->left);//左子树:右;右子树:左
            bool result = result1 && result2;//左子树:中;右子树:中(逻辑处理)
            return result;
        }
        return false;
    }
};
​
//方法二:迭代
//使用队列实现
class Solution2 {
public:
    bool isSymmetric(TreeNode* root) {
        if (root == nullptr) return true;
        if (root->left == nullptr && root->right == nullptr) return true;
        else if (root->left == nullptr || root->right == nullptr) return false;
        //以上排除了根节点左右孩子都为空,根节点左右孩子其中一个为空的情况,剩下的就是左右孩子都不为空的情况
        queue<TreeNode*> que;
        que.push(root->left);
        que.push(root->right);
        while (!que.empty()) {
            TreeNode* node1 = que.front();
            que.pop();
            TreeNode* node2 = que.front();
            que.pop();
            if (node1->val != node2->val) return false;
​
            if (node1->left == nullptr && node2->right == nullptr);
            else if (node1->left == nullptr || node2->right == nullptr) return false;
            else {
                que.push(node1->left);
                que.push(node2->right);
            }
​
            if (node1->right == nullptr && node2->left == nullptr);
            else if (node1->right == nullptr || node2->left == nullptr) return false;
            else {
                que.push(node1->right);
                que.push(node2->left);
            }
        }
        return true;
    }
};
​
//迭代
//使用队列实现,代码更简洁
class Solution3 {
public:
    bool isSymmetric(TreeNode* root) {
        if (root == nullptr) return true;
        queue<TreeNode*> que;
        que.push(root->left);
        que.push(root->right);
        while (!que.empty()) {
            TreeNode* node1 = que.front();
            que.pop();
            TreeNode* node2 = que.front();
            que.pop();
            if (node1 != nullptr && node2 == nullptr) return false;
            else if (node1 == nullptr && node2 != nullptr) return false;
            else if (node1 == nullptr && node2 == nullptr);
            else if (node1->val != node2->val) return false;
            else if (node1->val == node2->val) { //其实这里的if语句写不写都可,因为前面把“这种情况”以外的所有情况都列举出来了
                que.push(node1->left);
                que.push(node2->right);
                que.push(node1->right);
                que.push(node2->left);
            }
        }
        return true;
    }
};
​
//迭代
//使用“栈”实现,把左右两个子树要比较的元素顺序放进一个容器,然后成对成对的取出来进行比较,只要将上面使用“队列”的方法中的队列改成栈即可,其余的代码不用改变
//这里给出更简洁的代码
class Solution4 {
public:
    bool isSymmetric(TreeNode* root) {
        if (root == nullptr) return true;
        stack<TreeNode*> sta;
        sta.push(root->left);
        sta.push(root->right);
        while (!sta.empty()) {
            TreeNode* node1 = sta.top();
            sta.pop();
            TreeNode* node2 = sta.top();
            sta.pop();
            if (!node1 && !node2) continue;
            if (!node1 || !node2 || (node1->val != node2->val)) {
                return false;
            }
            sta.push(node1->left);
            sta.push(node2->right);
            sta.push(node1->right);
            sta.push(node2->left);
        }
        return true;
    }
};

代码(Java):

//迭代
class
Solution { public boolean isSymmetric(TreeNode root) { if (root == null) return true; Deque<TreeNode> que = new LinkedList<>(); que.offer(root.left); que.offer(root.right); while (!que.isEmpty()) { TreeNode node1 = que.poll(); TreeNode node2 = que.poll(); ​ if (node1 == null && node2 == null); else if (node1 == null || node2 == null || (node1.val != node2.val)) return false; else { que.offer(node1.left); que.offer(node2.right); que.offer(node1.right); que.offer(node2.left); } } return true; } }

分析:

方法一:递归

  • 时间复杂度:这里遍历了这棵树,渐进时间复杂度为O(n)。

  • 空间复杂度:与递归使用的栈空间有关,这里递归层数不超过 n,故渐进空间复杂度为 O(n)。

方法二:迭代

  • 时间复杂度:O(n),遍历了这棵树。

  • 空间复杂度:这里用一个队列来维护节点,每个节点最多进队一次,出队一次,队列中最多不会超过 n 个点,故渐进空间复杂度为 O(n)。

参考链接

代码随想录

 

posted @ 2021-11-30 08:22  wltree  阅读(24)  评论(0编辑  收藏  举报