掘金团队号上线,助你 Offer 临门! 点击 查看详情
一、题目描述
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
示例:
例如,二叉树 [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
输入:
root = [1,2,2,3,4,4,3]
root = [1,2,2,null,3,null,3]
输出:
true
false
限制
0 <= 节点个数 <= 1000
二、思路分析
我的思路
- 考虑使用层次遍历然后计算这一层上所有节点是否对称就可以了
- 我以为层次遍历的方式去判断会比递归好些,但其实不是这样。
- 递归的思想也很简单,递归函数传入2个节点:一个最左边的,一个最右边的
最佳思路
- 采用递归去做,
- 先确认下递归的函数要干什么?
- 函数的作用是判断传入的两个树是否镜像。
- 输入:TreeNode left, TreeNode right
- 输出:是:true,不是:false
- 递归停止的条件是什么?
- 左节点和右节点都为空 -> 到底部了都长得一样 ->true
- 左节点为空的时候右节点不为空,或反之 -> 长得不一样-> false
- 左右节点值不相等 -> 长得不一样 -> false
- 从某层到下一层的关系是什么?
- 要想两棵树镜像,那么一棵树左边的左边要和二棵树右边的右边镜像,一棵树左边的右边要和二棵树右边的左边镜像
- 调用递归函数传入左左和右右
- 调用递归函数传入左右和右左
- 只有左左和右右镜像且左右和右左镜像的时候,我们才能说这两棵树是镜像的!
- 先确认下递归的函数要干什么?
三、AC 代码
我的写法:
// 采用的层次遍历去做的,结果很复杂
public boolean isSymmetric(TreeNode root) {
if (root == null) {
return true;
}
List<TreeNode> levelNodes = new ArrayList<
levelNodes.add(root.left);
levelNodes.add(root.right);
while (true) {
int index = 0;
// 比较一层是否相同
while (true) {
TreeNode pre = levelNodes.get(inde
TreeNode last = levelNodes.get(lev
if (pre != null && last != null) {
if (pre.val != last.val) {
return false;
}
} else {
if (pre != last) {
return false;
}
}
index++;
if (index > (levelNodes.size() / 2
break;
}
}
//添加下一层
boolean allNull = true;
List<TreeNode> newLevelNodes = new Arr
for (TreeNode n : levelNodes) {
if (n != null) {
if (n.left != null || n.right
allNull = false;
}
newLevelNodes.add(n.left);
newLevelNodes.add(n.right);
}
}
if (allNull) {
return true;
}
levelNodes = newLevelNodes;
}
}
最佳写法
public boolean isSymmetricBetter(TreeNode root) {
return root == null || recur(root.left, root.right);
}
/**
* 递归
*/
boolean recur(TreeNode L, TreeNode R) {
if (L == null && R == null) {
return true;
}
if (L == null || R == null || L.val != R.val) {
return false;
}
// 左子树的左边和右子树的右边去比较, 左子树的右边,和右子树的左边进行比较 --- 这点清楚了很重要
return recur(L.left, R.right) && recur(L.right, R.left);
}
四、总结
主要考的是递归的思路是否清晰!