二叉树

前序遍历

preorder.png
  1. ->->
function preorderTraversal(root: TreeNode | null): number[] {
    function dfs(root) {
        if (!root) return // 节点不存在,跳出
 
        res.push(root.val) // 根
        dfs(root.left) // 左
        dfs(root.right) // 右
    }
 
    let res = []
    dfs(root)
    return res
};

中序遍历

inorder.png
  1. ->->
function inorderTraversal(root: TreeNode | null): number[] {
    function dfs(root) {
        if (!root) return // 节点不存在,跳出
 
        dfs(root.left) // 左
        res.push(root.val) // 根
        dfs(root.right) // 右
    }
 
    let res = []
    dfs(root)
    return res
};

后序遍历

postorder.png
  1. ->->
function postorderTraversal(root: TreeNode | null): number[] {
    function dfs(root) {
        if (!root) return // 节点不存在,跳出
 
        dfs(root.left) // 左
        dfs(root.right) // 右
        res.push(root.val) // 根
    }
 
    let res = []
    dfs(root)
    return res
};

层序遍历

levelorder.png
  1. ->->
function levelOrder(root: TreeNode | null): number[][] {
    function bfs(root) {
        if (!root) return // 节点不存在,跳出
 
        let level = [root]
        while (level.length > 0) {
            let nextLevel = []
            for (let l of level) {
                if (l.left) nextLevel.push(l.left)
                if (l.right) nextLevel.push(l.right)
            }
            res.push(level.map(l => l.val))  
            level = nextLevel // 更新下一层
        }
    }
 
    let res = []
    bfs(root)
    return res
};

节点个数

  1. 使用前序遍历,记录节点个数
function countNodes(root: TreeNode | null): number {
    function dfs(root) {
        if (!root) return // 节点不存在,跳出
 
        count++ // 根
        dfs(root.left) // 左
        dfs(root.right) // 右
    }
 
    let count = 0
    dfs(root)
    return count
};

最大深度

  1. 最大深度 = 子节点的最大深度 + 1
function maxDepth(root: TreeNode | null): number {
    if (!root) return 0
 
    let [left, right] = [maxDepth(root.left), maxDepth(root.right)]
    return Math.max(left, right) + 1
};

最小深度

  1. 最小深度 = 子节点的最小深度 + 1(需要左右节点都存在)
function minDepth(root: TreeNode | null): number {
    if (!root) return 0
    if (!root.left && !root.right) return 1
    if (!root.left) return minDepth(root.right) + 1
    if (!root.right) return minDepth(root.left) + 1
    return Math.min(minDepth(root.left), minDepth(root.right)) + 1
};

平衡二叉树

  1. 遍历树的最大深度
  2. 每轮递归,检查 l - r
function isBalanced(root: TreeNode | null): boolean {
    function dfs(root) {
        if (!root) return 0
 
        let [l, r] = [dfs(root.left), dfs(root.right)]
        if (Math.abs(l - r) > 1) res = false
        return Math.max(l, r) + 1
    }
 
    let res = true
    dfs(root)
    return res
};

二叉树的直径

  1. 遍历树的最大深度
  2. 每轮递归,比较 l + r
function diameterOfBinaryTree(root: TreeNode | null): number {
    function dfs(root) {
        if (!root) return 0
 
        let [l, r] = [dfs(root.left), dfs(root.right)]
        res = Math.max(res, l + r)
        return Math.max(l, r) + 1
    }
 
    let res = 0
    dfs(root)
    return res
};

相同的树

  1. a, b 相同,需要满足 a.left === b.lefta.right === b.right
function isSameTree(p: TreeNode | null, q: TreeNode | null): boolean {
    if (!p && !q) return true
    if (!p || !q) return false
    if (p.val !== q.val) return false
    return isSameTree(p.left, q.left) && isSameTree(p.right, q.right)
};

对称二叉树

  1. a, b 对称,需要满足 a.left === b.righta.right === b.left
function isSymmetric(root: TreeNode | null): boolean {
    function dfs(p, q) {
        if (!p && !q) return true
        if (!p || !q) return false
        if (p.val !== q.val) return false
        return dfs(p.left, q.right) && dfs(p.right, q.left)
    }
 
    return dfs(root, root)
};

翻转二叉树

function invertTree(root) {
    if (!root) return root;
 
    [root.left, root.right] = [invertTree(root.right), invertTree(root.left)]
    return root
};

合并二叉树

function mergeTrees(root1: TreeNode | null, root2: TreeNode | null): TreeNode | null {
    if (!root1) return root2
    if (!root2) return root1
    
    let merged = new TreeNode(
        root1.val += root2.val,
        mergeTrees(root1.left, root2.left),
        mergeTrees(root1.right, root2.right)
    )
    return merged
};

路径总和

  1. 前序遍历,同时计算路径和
function hasPathSum(root: TreeNode | null, targetSum: number): boolean {
    function dfs(root, sum) {
        if (!root) return
 
        sum += root.val // 根
        if (!root.left && !root.right) { // 叶子节点
            if (sum === targetSum) res = true
        }
        dfs(root.left, sum) // 左
        dfs(root.right, sum) // 右
    }
 
    let res = false
    dfs(root, 0)
    return res
};

数字之和

  1. 前序遍历,同时计算路径和
function sumNumbers(root: TreeNode | null): number {
    function dfs(root, sum) {
        if (!root) return
 
        sum = 10 * sum + root.val //根
        if (!root.left && !root.right) res += sum
        dfs(root.left, sum) // 左
        dfs(root.right, sum) // 右
    }
 
    let res = 0
    dfs(root, 0)
    return res
};