开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情
给你一个二叉树的根节点 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.递归
对于二叉树的对称问题,需要比较的是二叉树的左右子树是否是相互翻转的,而不是比较左右节点,这里我用的递归来解决本题
本题的遍历顺序只能是“后序遍历”,因为我们要通过递归函数的返回值来判断两个子树的内侧节点和外侧节点是否相等。
又因为要遍历的两个子树的内侧和外侧节点,所以一个子树的遍历顺序为【左右中】而另一个子树的遍历顺序为【右左中】
递归三要素
1.确定递归函数的返回值和参数
参数:根节点下要比较的左子树节点和右子树节点
返回值:因为是比较,所以返回值类型为boolean型
2.确定终止条件
要比较两个节点数值相不相同,首先要把两个节点为空的情况弄清楚!否则在后面比较数值时就会爆空指针异常了
节点为空的情况有:
- 左子树为空时,而右子树不为空,返回false
- 左子树不为空时,右子树为空,返回false
- 左子树为空时,而右子树也为空,返回true
上面就是节点为空的情况,剩下的就是节点不为空的情况:
- 左右子树都不为空时,值却不相同,返回false
- 左右子树都不为空时,值却相同,返回true
3.确定单层递归逻辑
单层递归的逻辑就是处理左右子树不为空时,值是否相同的情况
- 先比较二叉树的内侧节点是否相同
- 再比较二叉树的外侧节点是否相同
- 当内外侧节点都相同时,这个二叉树就是对称的二叉树
代码实现如下:
public boolean isSymmetric(TreeNode root) {
if (root == null) {
return true;
}else {
return compare(root.left,root.right);
}
}
public boolean compare(TreeNode left,TreeNode right) {
//先判断左右子树存在情况
if (left != null && right == null) {
return false;
}else if (left == null && right != null) {
return false;
}else if (left != null && right != null) {
if (left.val != right.val) {
return false;
}
}else if (left == null && right == null) {
return true;
}
//递归左右子树的左右孩子相等情况
boolean ouside = compare(left.left,right.right);
boolean inside = compare(left.right,right.left);
return (ouside && inside);
}
2.迭代
迭代法的逻辑跟递归一样,只不过迭代法用到了队列这个数据结构,我们可以使用队列来比较两个树(根节点的左右子树)是否相互翻转
具体代码如下:
public boolean isSymmetric(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
if (root != null) {
queue.offer(root.left);
queue.offer(root.right);
}
while (!queue.isEmpty()) {
TreeNode leftNode = queue.poll();
TreeNode rightNode = queue.poll();
//当左右节点都为空时,说明是对称的
if (leftNode == null && rightNode == null) {
continue;
}
//左右节点有一个为空,或都不为空,但值不相同 就返回false
if ((leftNode == null || rightNode == null) || (leftNode.val != rightNode.val)) {
return false;
}
queue.offer(leftNode.left);//添加左节点的左孩子
queue.offer(rightNode.right);//添加右节点的右孩子
queue.offer(leftNode.right);//添加左节点的右孩子
queue.offer(rightNode.left);//添加右节点的左孩子
}
return true;
}