zhangdizhangdi

101. 对称二叉树 🟩

题目

LeetCode 简单

题目

给你一个二叉树的根节点 root , 检查它是否轴对称。

示例:
输入:root = [1,2,2,3,4,4,3]
输出:true

输入:root = [1,2,2,null,3,null,3]
输出:false

题解

方法:递归

DFS 深度优先 递归

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)
ts
function isSymmetric(root: TreeNode | null): boolean {
  const isSame = (left: TreeNode | null, right: TreeNode | null) => {
    console.log('left', left?.val, 'right', right?.val)

    if (!left && !right) return true
    if (
      left &&
      right &&
      left.val === right.val &&
      isSame(left.left, right.right) &&
      isSame(left.right, right.left)
    )
      return true
    return false
  }

  return isSame(root.left, root.right)
}

const p = new Tree([1, 2, 2, 3, 4, 4, 3, 5, 6, 7, 8, 8, 7, 6, 5]),
  q = new Tree([1, 2, 2, null, 3, null, 3])

console.log('🌰', isSymmetric(p.root))
console.log('🌰', isSymmetric(q.root))

方法:迭代

在 JS 中,既可以用pop() 弹出尾部,做深度优先遍历 DFS),也可以用队列shift() 弹出头部,做广度优先遍历 BFS)。两者逻辑在这道题里完全通用。

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)
js
// 1. 定义二叉树节点
class TreeNode {
  constructor(val, left = null, right = null) {
    this.val = val
    this.left = left
    this.right = right
  }
}

// ==========================================
// 核心算法:对称二叉树 (迭代法)
// ==========================================
var isSymmetric = function (root) {
  if (root === null) return true // 空树绝对对称

  // 初始化栈,把根节点的左孩子和右孩子作为第一对
  const stack = [[root.left, root.right]]

  while (stack.length > 0) {
    console.log(
      'stack',
      JSON.stringify(
        stack.map(pair => pair.map(node => (node ? node.val : null))),
      ),
    )

    // 弹出一对节点进行“镜像”比较
    const [leftNode, rightNode] = stack.pop()

    // 1. 两个都是 null,说明这对镜像分支走到底了,安全
    if (leftNode === null && rightNode === null) {
      continue
    }

    // 2. 一个为空另一个不为空,镜像被打破
    if (leftNode === null || rightNode === null) {
      return false
    }

    // 3. 值不相等,镜像被打破
    if (leftNode.val !== rightNode.val) {
      return false
    }

    // 走到这里说明当前的一对节点长得一样。
    // 开始【交叉配对】并压入栈中:
    // 外侧配外侧:左节点的左孩子,配上,右节点的右孩子
    stack.push([leftNode.left, rightNode.right])

    // 内侧配内侧:左节点的右孩子,配上,右节点的左孩子
    stack.push([leftNode.right, rightNode.left])
  }

  // 所有验证全部通过
  return true
}

// --- 运行测试 ---

// 树 A: 对称树[1, 2, 2, 3, 4, 4, 3]
//       1
//      / \
//     2   2
//    / \ / \
//   3  4 4  3
const treeA = new TreeNode(1)
treeA.left = new TreeNode(2, new TreeNode(3), new TreeNode(4))
treeA.right = new TreeNode(2, new TreeNode(4), new TreeNode(3))

// 树 B: 不对称树[1, 2, 2, null, 3, null, 3]
//       1
//      / \
//     2   2
//      \   \
//       3   3
const treeB = new TreeNode(1)
treeB.left = new TreeNode(2, null, new TreeNode(3))
treeB.right = new TreeNode(2, null, new TreeNode(3))

console.log('🌰 TreeA 是否对称? (预期: true) ->', isSymmetric(treeA))
console.log('-----------------------------')
console.log('🌰 TreeB 是否对称? (预期: false)->', isSymmetric(treeB))
执行结果
stack [[2,2]]
stack [[3,3],[4,4]]
stack [[3,3],[null,null],[null,null]]
stack [[3,3],[null,null]]
stack [[3,3]]
stack [[null,null],[null,null]]
stack [[null,null]]
🌰 TreeA 是否对称? (预期: true) -> true
-----------------------------
stack [[2,2]]
stack [[null,3],[3,null]]
🌰 TreeB 是否对称? (预期: false)-> false