力扣:101. 对称二叉树

题目链接101. 对称二叉树
题目

给你一个二叉树的根节点 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

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

方案一:递归
用递归法之前可以先提前了解“递归三部曲”。
本题的三部曲是:
1、确定递归的参数和返回值:对称二叉树主要是比较左右子树的节点值是否对称,可以推断出【参数:左右孩子节点,返回值:布尔类型】。

bool compare(TreeNode* leftNode, TreeNode* rightNode) {}

2、确定终止条件:如果传入的左右孩子节点都为空,则可以知道两节点对称;如果左右孩子节点任意一个为空或两节点不为空并且值不等,则两节点不对称。此时已经排除掉了节点为空的情况,那么剩下的就是左右节点不为空:左右都不为空,比较节点数值,不相同就return false,反之相同就return true。左右都不为空的情况则是交给递归内外侧的子树节点即可。

//左右孩子节点都为空,则两节点对称
if (!leftNode && !rightNode) return true;
//左右孩子节点任意一个为空,则两节点不对称
else if (!leftNode || !rightNode) return false;
//左右孩子节点不为空且值不等,则不对称
else if (leftNode->val != rightNode->val) return false;

3、确定单层逻辑:递归左右子树的外侧(左节点的左孩子和右节点的右孩子)和内侧(左节点的右孩子和右节点的左孩子),如果内外侧都对称,则return true,反之return false。

return compare(leftNode->left, rightNode->right) && compare(leftNode->right, rightNode->left);

代码(c++)

/**
 * 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) {
        if (!root) return true;
        return compare(root->left, root->right);
    }
private:
    //确定递归的参数和返回值
    //比较左右子树的节点值是否对称-->参数:左右孩子节点,返回值:布尔类型
    bool compare(TreeNode* leftNode, TreeNode* rightNode) {
        //确定终止条件
        //左右孩子节点都为空,则两节点对称
        if (!leftNode && !rightNode) return true;
        //左右孩子节点任意一个为空,则两节点不对称
        else if (!leftNode || !rightNode) return false;
        //左右孩子节点不为空且值不等,则不对称
        else if (leftNode->val != rightNode->val) return false;

        //确定单层逻辑
        //递归左右子树的外侧(左节点的左孩子和右节点的右孩子)和内侧(左节点的右孩子和右节点的左孩子)
        //如果外侧和内侧都对称则为true,反之则为false
        else return compare(leftNode->left, rightNode->right) && compare(leftNode->right, rightNode->left);
    }
};

方案二:迭代

1、使用队列来比较两个树(根节点的左右子树)是否相互翻转

//迭代
//用队列实现
class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        queue<TreeNode*> que;
        if (root) {
            //将根节点的左右孩子节点放入队列
            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;
            //如果左右孩子节点任意一个为空或两节点值不等,则不对称
            else 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;
    }
};

2、使用栈来比较两个树(根节点的左右子树)是否相互翻转
究其根本,本题就是比较根节点的左右子树是否相互翻转,所以无论使用队列还是用栈,目的都是一样的。因而用栈实现和用队列实现作用是相同的。

//迭代
//用栈实现
class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        stack<TreeNode*> stk;
        if (root) {
            //将根节点的左右孩子节点压栈
            stk.push(root->left);
            stk.push(root->right);
        }
        while (!stk.empty()) {
            TreeNode* rightNode = stk.top();   //取出右孩子节点
            stk.pop();
            TreeNode* leftNode = stk.top();  //取出左孩子节点
            stk.pop();
            //如果左右孩子节点都为空,则对称-->结束本次循环
            if (!leftNode && !rightNode) continue;
            //如果左右孩子节点任意一个为空或两节点值不等,则不对称
            else if (!leftNode || !rightNode || leftNode->val != rightNode->val) return false;
            //将树的外侧孩子节点压栈
            stk.push(leftNode->left);   //将左节点的左孩子压栈
            stk.push(rightNode->right); //将右节点的右孩子压栈
            //将树的内侧孩子节点压栈
            stk.push(leftNode->right);  //将左节点的右孩子压栈
            stk.push(rightNode->left);  //将右节点的左孩子压栈
        }
        return true;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追梦偏执狂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值