这是我参与8月更文挑战的第12天,活动详情查看:8月更文挑战
对称二叉树(题号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
进阶:
你可以运用递归和迭代两种方法解决这个问题吗?
链接
解释
这题啊,这题是经典遍历二叉树。
不过遍历的时候需要注意,不能一口气遍历完左子树,然后遍历右子树,再将右子树的遍历结果反转,进行这样的操作后可以通过99%的测试用例,但依旧有1%无法成功。
为什么会这样?因为这里的对称二叉树是镜像的操作,不管使用前序、中序、后序哪种遍历方式,反转遍历结果的不会是镜像的,有些特殊的测试用例是无法通过的,别问为什么,笔者试过。
剩下的办法就是只能一个节点一个节点的对比了,如果有子节点,就反向对比子节点,那拿第一个例子来说,一开始肯定会比较左右子树的2节点,发现二者一样,接下来就应该比较左子树2节点的左子树和右子树2节点的右子树,依次类推,从而形成镜像的比较。
这样做不仅仅能拿到正确的结果,还可以再遇到不相同节点时提前终止比较,相较于一次性拿到所有节点值的做法可以节省一部分性能。
下面看看代码。
自己的答案
无
更好的方法(递归)
相对来说递归的方法总是比迭代要简单一些,所以就先说递归吧,整体思路就是从根节点的左右节点开始,进行镜像比较👇:
function isSymmetric(root) {
function check(p, q) {
if (!p && !q) return true
if (!p || !q) return false
return p.val === q.val && check(p.left, q.right) && check(p.right, q.left)
}
return check(root.left, root.right)
}
比较过程主要分三种:
p和q都是null,证明二者相同,返回truep或者q有一个是null,证明二者不相同,返回falsep.val和q.val的值是否相同,返回true或者false
完成这三步的比较即可确定当前两个节点的值是否相同,接下来交叉比较二者的左右节点,这就完事了。
更好的方法(迭代)
迭代和平时遍历二叉树差不多,都需要借助一个栈来存储当前的节点。
在开始时,先将两个节点推入栈中,之后开始迭代,将两个节点依次取出来,对二者的值进行比较,比较过程和递归一样,完成比较发现没问题后,将二者的左右节点有序的推入到栈中,等待下依次迭代的开始。
function isSymmetric(root) {
function check(p, q) {
const arr = [p, q]
while (arr.length) {
p = arr.shift()
q = arr.shift()
if (!p && !q) continue
if ((!p || !q) || (p.val !== q.val)) return false
arr.push(q.left)
arr.push(p.right)
arr.push(q.right)
arr.push(p.left)
}
return true
}
return check(root.left, root.right)
}
PS:想查看往期文章和题目可以点击下面的链接:
这里是按照日期分类的👇
经过有些朋友的提醒,感觉也应该按照题型分类
这里是按照题型分类的👇