记录 1 道算法题
对称二叉树
一棵树中间轴对称,在广度遍历的时候,需要注意推入数组的时候要区分左右节点。
a
b c
d e
这种情况下,第三层推入数组时是 [d,e]。这样看着是对称的,但其实是不对称的,所以要推入 undefined 进行占位,但是不用把一层占满,只需要如果左右节点其中一个有值的话,另一个是空的时候就填入 undefined 就可以了。
例如 [undefined, d, undefined, e],这样就可以判断出不对称。
- 广度优先
一开始打算正常从左到右的顺序存,然后判断头和尾是否相等,往中间收缩,但是这样就要遍历两遍,一边判断,一遍收集下一层的节点。
所以优化的方法是改变存入数组时的顺序。
function isSymmetric(root) {
const stack = [root.left, root.right]
while (stack.length) {
// 改变后前两个节点是应该对称的节点
const n1 = stack.shift()
const n2 = stack.shift()
// 判断是否匹配
// 如果都是叶子节点就跳过
if (!n1 && !n2) continue
if (!n1 || !n2) return false
if (n1.val !== n2.val) return false
// 最左边和最右边一起推入
// a b c d,假如这一层是这样
// ad, bc 的推入
stack.push(n1.left, n2.right)
stack.push(n1.right, n2.left)
}
return true
}
- 深度优先
就是递归解决了,需要传入两个参数,分别是对称轴左边的节点和对称轴右边的节点。
当左边往左走的时候,右边往右走。当左边往右走的时候,左边往左走。
a a
b c c b
这种情况,当我们处在 a 节点的视角的时候, 左边的 a 往左走,与他对称的右边的 a 是要往右走。
function isSymmetric(root, root2 = root) {
// 都是空节点时不用判断
if (!root && !root2) return true
// 如果上面没进去,说明至少有一个不是空节点,
// 如果这里进去了说明至少有一个是空节点,就不匹配。
if (!root || !root2) return false
// 比较值
if (root.val !== root2.val) return false
// 反着走
return (
isSymmetric(root.left, root2.right) &&
isSymmetric(root.right, root2.left)
)
}