101. 对称二叉树
力扣链接https://leetcode.cn/problems/symmetric-tree/description/
题目描述:
给你一个二叉树的根节点 root
, 检查它是否轴对称。
示例 1:
输入:root = [1,2,2,3,4,4,3] 输出:true
示例 2:
输入:root = [1,2,2,null,3,null,3] 输出:false
思路分析:
对于二叉树是否对称,要比较的是根节点的左子树与右子树是不是相互翻转的,而不是比较左右子节点。所以在递归遍历的过程中,要同时遍历两棵子树。要比较子树的外侧与内侧。
递归实现
如果使用递归函数,则递归函数的参数应该是左右子树的根节点指针。同时,判断是否对称需要有bool类型的结果,所以,递归函数的返回值类型可以用bool。其形式如下:
bool compare(TreeNode * left, TreeNode * right){}
如此就完成了递归三部曲中的第一步:确定递归函数的参数和返回值
因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个左子树的遍历顺序是左右中,一个右子树的遍历顺序是右左中。
递归第二步:确认终止条件
首先需要对传入的两个子树根节点进行分析,一共有一下五种情况:
1.左子树空、右子树非空
2.左子树非空、右子树空
3.左子树空、右子树空
4.左子树非空、右子树非空,对应元素不相等
5.左子树非空、右子树非空,对应元素相等,需要继续判断
//存在右子树,不存在左子树 ---》不对称
if(left == nullptr && right != nullptr) return false;
//存在左子树,不存在右子树 ---》不对称
else if(left != nullptr && right == nullptr) return false;
//左右子树均不存在 ---》对称
else if(left == nullptr && right == nullptr) return true;
//左右子树均存在,但是对应子树根节点元素不相等 --》不对称
else if(left->val != right->val) return false;
上述代码是前四种情况,属于递归终止条件。
第五种情况就是需要继续遍历判断的,所以它属于递归第三步:确认单层递归逻辑
递归第三步:确认单层递归逻辑
继续遍历比较时,应该将左子树的左子树同右子树的右子树进行比较,因为这些都属于外侧。同时,还要将左子树的右同右子树的左进行比较,这些属于内侧。所以单层递归的逻辑如下:
//以上情况都不满足,则只剩下左右子树均存在,且子树根节点元素相等的情况。那么需要继续比较
bool outside = compare(left->left, right->right); //比较外侧,左子树的左与右子树的右比较
bool inside = compare(left->right, right->left); //比较内侧,左子树的右与右子树的左比较
if(outside && inside) //外侧内侧都相等return true;
else //否则return 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, TreeNode * right){//存在右子树,不存在左子树 ---》不对称if(left == nullptr && right != nullptr) return false;//存在左子树,不存在右子树 ---》不对称else if(left != nullptr && right == nullptr) return false;//左右子树均不存在 ---》对称else if(left == nullptr && right == nullptr) return true;//左右子树均存在,但是对应子树根节点元素不相等 --》不对称else if(left->val != right->val) return false;//以上情况都不满足,则只剩下左右子树均存在,且子树根节点元素相等的情况。那么需要继续比较bool outside = compare(left->left, right->right); //比较外侧,左子树的左与右子树的右比较bool inside = compare(left->right, right->left); //比较内侧,左子树的右与右子树的左比较if(outside && inside) //外侧内侧都相等return true;else //否则return false;}bool isSymmetric(TreeNode* root) {if(root==nullptr) return true;return compare(root->left, root->right);}
};
使用队列实现:
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;}// 左右一个节点不为空,或者都不为空但数值不相同,返回falseif ((!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;}
};
使用栈实现:
class Solution {
public:bool isSymmetric(TreeNode* root) {if (root == NULL) return true;stack<TreeNode*> st; // 这里改成了栈st.push(root->left);st.push(root->right);while (!st.empty()) {TreeNode* leftNode = st.top(); st.pop();TreeNode* rightNode = st.top(); st.pop();if (!leftNode && !rightNode) {continue;}if ((!leftNode || !rightNode || (leftNode->val != rightNode->val))) {return false;}st.push(leftNode->left);st.push(rightNode->right);st.push(leftNode->right);st.push(rightNode->left);}return true;}
};