「这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战」
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
解析
/*
二叉树是否对称:
即根节点的两个子树可以相互反转
所以我们需要比较的就是两棵子树:根节点的左子树和右子树
选择递归方法,同时遍历两棵树
这里只能选择后续遍历:一个树的遍历是左右中,另一个树的遍历是右左中
递归三部曲:
1、确定递归函数的参数与返回值
要比较的是左右两个子树,所以参数为左右子树的节点
返回值是比较的结果,相同就为true,否则为false
2、确定终止条件
要比较两个节点数值是否相同
首先要判断两个节点是否为空
(1)左节点为空,右节点不为空,返回 false
(2)左节点不为空,右节点为空,返回 false
(3)左右节点都为空,返回 true
再判断节点非空的情况
(1)左节点的值 == 右节点的值 , 返回 true
(2)左节点的值 != 右节点的值 , 返回 false
3、确定单层递归的逻辑
单层递归的逻辑就是处理左右节点不为空,且数值相同的情况
(1)树外侧是否对称:传入左节点的左孩子,右节点的右孩子
(2)树内侧是否对称,传入左节点的右孩子,右节点的左孩子
(3)如果内侧和外侧都对称,返回 true , 有一侧不对称,返回 false
*/
递归法
class Solution
{
public:
bool isSymmetric(TreeNode *root)
{
if (root == NULL)
{
return true;
}
return compare(root->left, root->right);
}
bool compare(TreeNode *left, TreeNode *right)
{
// 首先排除空节点的情况
if (left == NULL && right == NULL) // 左右节点均为空
{
return true;
}
else if (left == NULL && right != NULL) // 左节点为空,右节点非空
{
return false;
}
else if (left != NULL && right == NULL) // 左节点非空,右节点为空
{
return false;
}
// 排除数值不相同的情况
else if (left->val != right->val)
{
return false;
}
// 下面的是 左右节点都不为空,且数值相同的情况
// 此时递归处理,做下一层的判断
bool outside = compare(left->left, right->right); // 左节点的左子树,右节点的右子树
bool inside = compare(left->right, right->left); // 左节点的右子树,右节点的左子树
bool isSame = outside && inside; // 外侧和内侧都是相同则返回 true,否则返回false
return isSame;
}
};
迭代法(队列)
class Solution2
{
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
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;
}
};
迭代法(栈)
class Solution3
{
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;
}
else 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;
}
};