算法笔试-树

关于语言:一刷用 Golang,二刷用 Rust

题单来源于 分享丨【题单】链表、二叉树与回溯(前后指针/快慢指针/DFS/BFS/直径/LCA/一般树)

题单

遍历二叉树

题目 来源 难度 分数
144. 二叉树的前序遍历 简单
94. 二叉树的中序遍历 简单
145. 二叉树的后序遍历 简单
872. 叶子相似的树 第 94 场周赛 Q1 简单 1288
404. 左叶子之和 简单
671. 二叉树中第二小的节点 简单

自顶向下 DFS

题目 来源 难度 分数
104. 二叉树的最大深度 简单
111. 二叉树的最小深度 简单
112. 路径总和 简单
129. 求根节点到叶节点数字之和 中等
199. 二叉树的右视图 中等
1448. 统计二叉树中好节点的数目 第 26 场双周赛 Q3 中等 1360
1457. 二叉树中的伪回文路径 第 190 场周赛 Q3 中等 1405
1315. 祖父节点值为偶数的节点和 第 17 场双周赛 Q3 中等 1427
988. 从叶结点开始的最小字符串 第 122 场周赛 Q2 中等 1429
1026. 节点与其祖先之间的最大差值 第 132 场周赛 Q2 中等 1446
1022. 从根到叶的二进制数之和 第 131 场周赛 Q2 简单 1462
623. 在二叉树中增加一行 中等
1372. 二叉树中的最长交错路径 第 21 场双周赛 Q3 中等 1713
971. 翻转二叉树以匹配先序遍历 第 118 场双周赛 Q3 中等 1787
1443. 收集树上所有苹果的最少时间 第 188 场周赛 Q3 中等 1683
1377. T 秒后青蛙的位置 第 179 场周赛 Q4 困难 1824
993. 二叉树的堂兄弟节点 第 124 场周赛 Q1 简单 1288

自底向上 DFS

题目 来源 难度 分数
965. 单值二叉树 第 117 场周赛 Q1 简单 1178
100. 相同的树 简单
101. 对称二叉树 简单
951. 翻转等价二叉树 第 113 场周赛 Q2 中等 1477
110. 平衡二叉树 简单
226. 翻转二叉树 简单
617. 合并二叉树 简单
2331. 计算布尔二叉树的值 第 82 场双周赛 Q1 简单 1304
508. 出现次数最多的子树元素和 中等
563. 二叉树的坡度 简单
606. 根据二叉树创建字符串 中等
2265. 统计值等于子树平均值的节点数 第 292 场周赛 Q2 中等 1473
1339. 分裂二叉树的最大乘积 第 174 场周赛 Q3 中等 1675
1145. 二叉树着色游戏 第 148 场周赛 Q2 中等 1741
572. 另一棵树的子树 简单
1530. 好叶子节点对的数量 第 199 场周赛 Q3 中等 1746
814. 二叉树剪枝 第 79 场周赛 Q2 中等 1380
1325. 删除给定值的叶子节点 第 172 场周赛 Q3 中等 1407
1110. 删点成林 第 144 场周赛 Q3 中等 1511
1376. 通知所有员工所需的时间 第 179 场周赛 Q3 中等 1561

树的直径

题目 来源 难度 分数
543. 二叉树的直径 简单
687. 最长同值路径 中等
124. 二叉树中的最大路径和 困难
2385. 感染二叉树需要的总时间 第 307 场周赛 Q3 中等 1711

最近公共祖先(LCA)

题目 来源 难度 分数
236. 二叉树的最近公共祖先 中等
235. 二叉搜索树的最近公共祖先 中等
1123. 最深叶节点的最近公共祖先 第 145 场周赛 Q2 中等 1607

BFS

题目 来源 难度 分数
102. 二叉树的层序遍历 中等
103. 二叉树的锯齿形层序遍历 中等
107. 二叉树的层序遍历 II 中等
513. 找树左下角的值 中等
515. 在每个树行中找最大值 中等
637. 二叉树的层平均值 简单
1161. 最大层内元素和 第 150 场周赛 Q2 中等 1250
2583. 二叉树中的第 K 大层和 第 335 场周赛 Q2 中等 1374
1302. 层数最深叶子节点的和 第 16 场双周赛 Q3 中等 1388

题解

144. 二叉树的前序遍历

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func preorderTraversal(root *TreeNode) []int {
    ans := make([]int, 0)
    var dfs func(*TreeNode)
    dfs = func (r *TreeNode) {
        if r == nil {
            return
        }
        ans = append(ans, r.Val)
        dfs(r.Left)
        dfs(r.Right)
    }
    dfs(root)
    return ans
}

94. 二叉树的中序遍历

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func inorderTraversal(root *TreeNode) (ans []int) {
    var dfs func(*TreeNode)
    dfs = func(r *TreeNode) {
        if r == nil {
            return
        }
        dfs(r.Left)
        ans = append(ans, r.Val)
        dfs(r.Right)
    }
    dfs(root)
    return 
}

145. 二叉树的后序遍历

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func postorderTraversal(root *TreeNode) (ans []int) {
    var dfs func(*TreeNode)
    dfs = func(r *TreeNode) {
        if r == nil {
            return
        }
        dfs(r.Left)
        dfs(r.Right)
        ans = append(ans, r.Val)
    }
    dfs(root)
    return
}

872. 叶子相似的树

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func leafSimilar(root1 *TreeNode, root2 *TreeNode) bool {
    var dfs func(*TreeNode, *[]int)
    dfs = func(r *TreeNode, path *[]int) {
        if r == nil {
            return
        }
        if r.Left == nil && r.Right == nil {
            *path = append(*path, r.Val)
        }
        dfs(r.Left, path)
        dfs(r.Right, path)
    }
    p1, p2 := make([]int, 0), make([]int, 0)
    dfs(root1, &p1)
    dfs(root2, &p2)
    if len(p1) != len(p2) {
        return false
    }
    for i := 0; i < len(p1); i++ {
        if p1[i] != p2[i] {
            return false
        }
    }
    return true
}

404. 左叶子之和

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func sumOfLeftLeaves(root *TreeNode) int {
    if root == nil {
        return 0
    } 
    ans := 0
    if root.Left != nil && root.Left.Left == nil && root.Left.Right == nil {
        ans = root.Left.Val
    }
    return ans + sumOfLeftLeaves(root.Left) + sumOfLeftLeaves(root.Right)
}

671. 二叉树中第二小的节点

题目描述,「如果一个节点有两个子节点的话,那么该节点的值等于两个子节点中较小的一个」,因此对于二叉树中的任意节点 \(x\)\(x\) 的值不大于以 \(x\) 为根的子树中所有节点的值。

\(x\) 为二叉树的根节点,可以得出结论:二叉树根节点的值即为所有节点中的最小值。

func findSecondMinimumValue(root *TreeNode) int {
    ans := -1
    rootVal := root.Val
    var dfs func(*TreeNode)
    dfs = func(node *TreeNode) {
        if node == nil || ans != -1 && node.Val >= ans {
            return
        }
        if node.Val > rootVal {
            ans = node.Val
        }
        dfs(node.Left)
        dfs(node.Right)
    }
    dfs(root)
    return ans
}

104. 二叉树的最大深度

解法一:自顶向下,解法二:自底向上

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func maxDepth(root *TreeNode) (ans int) {
    var dfs func(*TreeNode, int)
    dfs = func(r *TreeNode, depth int) {
        if r == nil {
            return
        }
        ans = max(ans, depth)
        dfs(r.Left, depth + 1)
        dfs(r.Right, depth + 1)
    }
    dfs(root, 1)
    return ans
}
func maxDepth(root *TreeNode) int {
    var dfs func(*TreeNode) int
    dfs = func(r *TreeNode) int {
        if r == nil {
            return 0
        }
        depth := max(dfs(r.Left), dfs(r.Right)) + 1
        return depth
    }
    return dfs(root)
}

111. 二叉树的最小深度

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func minDepth(root *TreeNode) int {
    ans := math.MaxInt
    var dfs func(*TreeNode, int) 
    dfs = func(r *TreeNode, p int) {
        if r == nil {
            return
        }
        if r.Left == nil && r.Right == nil {
            ans = min(ans, p)
        }
        dfs(r.Left, p + 1)
        dfs(r.Right, p + 1)
    }
    dfs(root, 1)
    if ans == math.MaxInt {
        return 0
    }
    return ans
}
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func minDepth(root *TreeNode) int {
    var dfs func(*TreeNode) int
    dfs = func(root *TreeNode) int {
        if root == nil {
            return 0
        }
        l := dfs(root.Left)
        r := dfs(root.Right)
        if l > 0 && r > 0 {
            return min(l, r) + 1
        } else {
            return l + r + 1
        }
    }
    return dfs(root)
}

112. 路径总和

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func hasPathSum(root *TreeNode, targetSum int) bool {
    var dfs func(*TreeNode, int) bool
    dfs = func(r *TreeNode, s int) bool {
        if r == nil {
            return false
        }
        s += r.Val
        if s == targetSum && r.Left == nil && r.Right == nil {
            return true
        }
        return dfs(r.Left, s) || dfs(r.Right, s)
    }    
    return dfs(root, 0)
}

129. 求根节点到叶节点数字之和

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func sumNumbers(root *TreeNode) (ans int) {
    var dfs func(*TreeNode, int)
    dfs = func(r *TreeNode, num int) {
        if r == nil {
            return
        }
        num = num * 10 + r.Val
        if r.Left == nil && r.Right == nil {
            ans += num
        }
        dfs(r.Left, num)
        dfs(r.Right, num)
    }
    dfs(root, 0)
    return
}

199. 二叉树的右视图

先递归右子树,再递归左子树,当某个深度首次到达时,对应的节点就在右视图中。

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func rightSideView(root *TreeNode) (ans []int) {
    var dfs func(*TreeNode, int) 
    dfs = func(r *TreeNode, depth int) {
        if r == nil {
            return
        }
        if depth == len(ans) {
            ans = append(ans, r.Val)
        }
        dfs(r.Right, depth + 1)
        dfs(r.Left, depth + 1)
    }
    dfs(root, 0)
    return
}

1457. 二叉树中的伪回文路径

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func pseudoPalindromicPaths (root *TreeNode) (ans int) {
    var dfs func(*TreeNode, int)
    dfs = func(r *TreeNode, s int) {
        if r == nil {
            return
        }
        s ^= (1 << r.Val)
        if r.Left == nil && r.Right == nil && bits.OnesCount(uint(s)) <= 1 {
            ans++
        }
        dfs(r.Left, s)
        dfs(r.Right, s)
    }
    dfs(root, 0)
    return
}

1315. 祖父节点值为偶数的节点和

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func sumEvenGrandparent(root *TreeNode) (ans int) {
    var dfs func(*TreeNode, int, int) 
    dfs = func(r *TreeNode, f, gf int) {
        if r == nil {
            return
        }
        if gf % 2 == 0 {
            ans += r.Val
        }
        dfs(r.Left, r.Val, f)
        dfs(r.Right, r.Val, f)
    }
    dfs(root, -1, -1)
    return 
}

988. 从叶结点开始的最小字符串

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func smallestFromLeaf(root *TreeNode) (ans string) {
    var dfs func(*TreeNode, string)
    dfs = func(r *TreeNode, path string) {
        if r == nil {
            return
        }
        path = string('a' + r.Val) + path
        if r.Left == nil && r.Right == nil {
            if ans == "" {
                ans = path
            } else {
                ans = min(ans, path)
            }
        }
        dfs(r.Left, path)
        dfs(r.Right, path)
    }
    dfs(root, "")
    return
}

1026. 节点与其祖先之间的最大差值

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func maxAncestorDiff(root *TreeNode) (ans int) {
    ans = math.MinInt
    var dfs func(*TreeNode, int, int)
    dfs = func(r *TreeNode, mx, mn int) {
        if r == nil {
            return
        }
        ans = max(ans, mx - r.Val)
        ans = max(ans, r.Val - mn)
        dfs(r.Left, max(mx, r.Val), min(mn, r.Val))
        dfs(r.Right, max(mx, r.Val), min(mn, r.Val))
    }
    dfs(root, root.Val, root.Val)
    return
}

1022. 从根到叶的二进制数之和

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func sumRootToLeaf(root *TreeNode) (ans int) {
    var dfs func(*TreeNode, int)
    dfs = func(r *TreeNode, num int) {
        if r == nil {
            return
        }
        num = num << 1 | r.Val
        if r.Left == r.Right {
            ans += num
        }
        dfs(r.Left, num)
        dfs(r.Right, num)
    } 
    dfs(root, 0)
    return
}

623. 在二叉树中增加一行

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func addOneRow(root *TreeNode, val int, depth int) *TreeNode {
    var dfs func(*TreeNode, int)
    dfs = func(r *TreeNode, p int) {
        if r == nil {
            return
        }
        if depth - 1 == p {
            // 创建两个节点
            newLeft := &TreeNode{val, r.Left, nil}
            newRight := &TreeNode{val, nil, r.Right}
            r.Left, r.Right = newLeft, newRight
        } else {
            dfs(r.Left, p + 1)
            dfs(r.Right, p + 1)
        }
    }
    if depth == 1 {
        return &TreeNode{val, root, nil}
    }
    dfs(root, 1)
    return root 
}

1372. 二叉树中的最长交错路径

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func longestZigZag(root *TreeNode) (ans int) {
    var dfs func(*TreeNode, int, int) 
    dfs = func(r *TreeNode, dir, cnt int) {
        if r == nil {
            return
        }
        ans = max(ans, cnt)
        // 延续上一次的继续走
        if dir == 0 {
            dfs(r.Right, dir ^ 1, cnt + 1)
            // 以当前节点为根节点
            dfs(r.Left, 0, 1)
        } else if dir == 1 {
            dfs(r.Left, dir ^ 1, cnt + 1) 
            dfs(r.Right, 1, 1)
        }
    }
    dfs(root.Left, 0, 1)
    dfs(root.Right, 1, 1)
    return
}

971. 翻转二叉树以匹配先序遍历

进行深度优先遍历,如果遍历到某一个节点的时候,节点值不能匹配,那么答案一定是 -1

否则,当期望的下一个数字与即将遍历的子节点的值不同的时候,就需要翻转一下当前节点。

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func flipMatchVoyage(root *TreeNode, voyage []int) []int {
    ans := make([]int, 0)
    idx := 0
    var dfs func(*TreeNode) bool
    dfs = func(r *TreeNode) bool {
        if r == nil {
            return true
        }
        if r.Val != voyage[idx] {
            return false
        }
        idx += 1
        if r.Left != nil && r.Left.Val != voyage[idx] {
            ans = append(ans, r.Val)
            return dfs(r.Right) && dfs(r.Left)
        } else {
            return dfs(r.Left) && dfs(r.Right)
        }
    }
    if dfs(root) {
        return ans
    }
    return []int{-1} 
}

965. 单值二叉树

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isUnivalTree(root *TreeNode) bool {
    var dfs func(r, p *TreeNode) bool
    dfs = func(r, p *TreeNode) bool {
        if r == nil {
            return true
        }
        if r.Val != p.Val {
            return false
        }
        return dfs(r.Left, r) && dfs(r.Right, r)
    }
    return dfs(root, root)
}

100. 相同的树

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isSameTree(p *TreeNode, q *TreeNode) bool {
    if p == nil && q == nil {
        return true
    } 
    if p == nil || q == nil {
        return false
    } else if (p.Val != q.Val) {
        return false
    }
    return isSameTree(p.Left, q.Left) && isSameTree(p.Right, q.Right)
}

101. 对称二叉树

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isSymmetric(root *TreeNode) bool {
    var dfs func(a, b *TreeNode) bool 
    dfs = func(a, b *TreeNode) bool {
        if a == nil && b == nil {
            return true
        }
        if a == nil || b == nil {
            return false
        }
        return a.Val == b.Val && dfs(a.Left, b.Right) && dfs(a.Right, b.Left) 
    } 
    return dfs(root.Left, root.Right)
}

951. 翻转等价二叉树

如果二叉树 root1,和 root2 根节点值相等,那么只需要检查它们的孩子是不是相等就可以了。存在两种情况:

  • 都为 null
  • 值相等孩子是否相等。由于可以翻转,所以需要判断两种情况。
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func flipEquiv(root1 *TreeNode, root2 *TreeNode) bool {
    if root1 == nil && root2 == nil {
        return true
    } 
    if root1 == nil || root2 == nil {
        return false 
    }
    if root1.Val != root2.Val {
        return false
    } 
    return (flipEquiv(root1.Left, root2.Left) && flipEquiv(root1.Right, root2.Right)) || (flipEquiv(root1.Left, root2.Right) && flipEquiv(root1.Right, root2.Left))
}

110. 平衡二叉树

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isBalanced(root *TreeNode) bool {
    var dfs func(*TreeNode) int
    dfs = func(r *TreeNode) int {
        if r == nil {
            return 0
        }
        depthL := dfs(r.Left)
        if depthL == -1 {
            return -1
        }
        depthR := dfs(r.Right)
        if depthR == -1 {
            return -1
        }
        if abs(depthL - depthR) > 1 {
            return -1
        }
        return max(depthL, depthR) + 1
    }
    return dfs(root) != -1
}
func abs(v int) int {
    if v < 0 {
        return -v
    }
    return v
}

226. 翻转二叉树

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func invertTree(root *TreeNode) *TreeNode {
    var dfs func(c *TreeNode) *TreeNode
    dfs = func(c *TreeNode) *TreeNode {
        if c == nil {
            return nil
        }
        l, r := dfs(c.Left), dfs(c.Right)
        c.Left, c.Right = r, l
        return c
    }
    return dfs(root)
}

617. 合并二叉树

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
    var dfs func(p, q *TreeNode) *TreeNode
    dfs = func(p, q *TreeNode) *TreeNode {
        if p == nil && q == nil {
            return nil
        } else if p == nil {
            return q
        } else if q == nil {
            return p
        } else {
            p.Val += q.Val
        }
        p.Left = dfs(p.Left, q.Left)
        p.Right = dfs(p.Right, q.Right)
        return p
    }
    return dfs(root1, root2)
}

2331. 计算布尔二叉树的值

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func evaluateTree(root *TreeNode) bool {
    var dfs func(c *TreeNode) bool
    dfs = func(c *TreeNode) bool {
        if c == nil {
            return true
        }
        if c.Left == c.Right {
            return c.Val == 1
        }
        l, r := dfs(c.Left), dfs(c.Right)
        if c.Val == 2 {
            return l || r
        } else {
            return l && r
        }
    }
    return dfs(root)
}

508. 出现次数最多的子树元素和

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func findFrequentTreeSum(root *TreeNode) []int {
    var dfs func(r *TreeNode) int
    cnt := make(map[int]int) 
    dfs = func(c *TreeNode) int {
        if c == nil {
            return 0
        }
        lSum, rSum := dfs(c.Left), dfs(c.Right)
        cnt[lSum + rSum + c.Val]++
        return lSum + rSum + c.Val
    }
    dfs(root)
    mx := 0
    for _, v := range cnt {
        mx = max(mx, v)
    }
    ans := make([]int, 0)
    for k, v := range cnt {
        if v == mx {
            ans = append(ans, k)
        }
    }
    return ans
}

563. 二叉树的坡度

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func findTilt(root *TreeNode) int {
    ans := 0
    var dfs func(c *TreeNode) int
    dfs = func(c *TreeNode) int {
        if c == nil {
            return 0
        }
        l, r := dfs(c.Left), dfs(c.Right)
        ans += abs(l - r)
        return l + r + c.Val
    }
    dfs(root)
    return ans
}
func abs(v int) int { 
    if v < 0 { 
        return -v 
    }
    return v
}

606. 根据二叉树创建字符串

func tree2str(root *TreeNode) string {
    switch {
    case root == nil:
        return ""
    case root.Left == nil && root.Right == nil:
        return strconv.Itoa(root.Val)
    case root.Right == nil:
        return fmt.Sprintf("%d(%s)", root.Val, tree2str(root.Left))
    default:
        return fmt.Sprintf("%d(%s)(%s)", root.Val, tree2str(root.Left), tree2str(root.Right))
    }
}

2265. 统计值等于子树平均值的节点数

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func averageOfSubtree(root *TreeNode) (ans int) {
    var dfs func(*TreeNode) (int, int)
    dfs = func(c *TreeNode) (int, int) {
        if c == nil {
            return 0, 0
        }
        l, lCnt := dfs(c.Left)
        r, rCnt := dfs(c.Right)
        sum := l + r + c.Val
        cnt := lCnt + rCnt + 1
        if sum / cnt == c.Val {
            ans++
        } 
        return sum, cnt
    }
    dfs(root)
    return
}

1339. 分裂二叉树的最大乘积

第一遍 dfs 求总和,第二遍枚举断哪条边

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func maxProduct(root *TreeNode) int {
    mod := int64(1e9+7)
    ans, total := int64(0), int64(0)
    var dfs func(*TreeNode) int64
    dfs = func(c *TreeNode) int64 {
        if c == nil {
            return 0
        }
        sum := int64(c.Val) + dfs(c.Left) + dfs(c.Right)
        ans = max(ans, sum * (total - sum))
        return sum
    }
    total = dfs(root)
    dfs(root)
    return int(ans % mod)
}

1145. 二叉树着色游戏

蓝色最优的点只有三个点可以选,就是红色点的三个相邻节点,所以只需要判断这三种情况即可。

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func btreeGameWinningMove(root *TreeNode, n int, x int) bool {
    var dfs func(*TreeNode) int
    s1, s2 := 0, 0
    dfs = func(c *TreeNode) int {
        if c == nil {
            return 0
        }
        l, r := dfs(c.Left), dfs(c.Right)
        if c.Val == x {
            s1, s2 = l, r
        }
        return l + r + 1
    }
    dfs(root)
    return s1 > (n - s1) || s2 > (n - s2) || (n - s1 - s2 - 1) > (s1 + s2 + 1)
}

572. 另一棵树的子树

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isSame(s, t *TreeNode) bool {
    if s == nil && t == nil {
        return true
    }
    if s == nil || t == nil {
        return false
    }
    if s.Val != t.Val {
        return false
    }
    return isSame(s.Left, t.Left) && isSame(s.Right, t.Right)
}
func isSubtree(root *TreeNode, subRoot *TreeNode) bool {
    if root == nil {
        return false
    }
    if isSame(root, subRoot) {
        return true
    }
    return isSubtree(root.Left, subRoot) || isSubtree(root.Right, subRoot)
}

1530. 好叶子节点对的数量

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func countPairs(root *TreeNode, distance int) (ans int) {
    var dfs func(*TreeNode) []int
    dfs = func(c *TreeNode) (ret []int) {
        if c == nil {
            return []int{}
        }
        if c.Left == c.Right {
            return []int{1}
        }
        left := dfs(c.Left)
        right := dfs(c.Right)
        for _, l := range left {
            ret = append(ret, l + 1)
            
        }
        for _, r := range right {
            ret = append(ret, r + 1)
        }
        for _, l := range left {
            for _, r := range right {
                if l + r <= distance {
                    ans++
                }
            }
        }
        return
    }
    dfs(root)
    return
}

814. 二叉树剪枝

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func pruneTree(root *TreeNode) *TreeNode {
    if root == nil {
        return nil
    }
    root.Left = pruneTree(root.Left)
    root.Right = pruneTree(root.Right)
    if root.Left == nil && root.Right == nil && root.Val == 0 {
        return nil
    }
    return root
}

1325. 删除给定值的叶子节点

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func removeLeafNodes(root *TreeNode, target int) *TreeNode {
    if root == nil {
        return nil
    }
    root.Left = removeLeafNodes(root.Left, target)
    root.Right = removeLeafNodes(root.Right, target)
    if root.Left == root.Right && root.Val == target {
        return nil
    }
    return root
}

1110. 删点成林

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func delNodes(root *TreeNode, to_delete []int) (ans []*TreeNode) {
    del := make(map[int]bool)
    for _, d := range to_delete {
        del[d] = true
    }
    var dfs func(*TreeNode) *TreeNode
    dfs = func(c *TreeNode) *TreeNode {
        if c == nil {
            return nil
        }
        // 如果 c 是要被删除的节点
        // 那么其左右孩子一定成为根节点
        c.Left = dfs(c.Left)
        c.Right = dfs(c.Right)
        if _, ok := del[c.Val]; !ok {
            // 不删
            return c
        }
        // 删
        if c.Left != nil {
            ans = append(ans, c.Left)
        }
        if c.Right != nil {
            ans = append(ans, c.Right)
        }
        return nil
    }
    if dfs(root) != nil {
        ans = append(ans, root)
    }
    return
}

543. 二叉树的直径

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func diameterOfBinaryTree(root *TreeNode) (ans int) {
    var dfs func(*TreeNode) int
    dfs = func(c *TreeNode) int {
        if c == nil {
            return -1
        }
        l, r := dfs(c.Left), dfs(c.Right)
        ans = max(ans, l + r + 2)
        return max(l, r) + 1
    }
    dfs(root)
    return
}

687. 最长同值路径

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func longestUnivaluePath(root *TreeNode) (ans int) {
    var dfs func(*TreeNode) int
    dfs = func(c *TreeNode) int {
        if c == nil {
            return -1
        }
        l, r := dfs(c.Left), dfs(c.Right)
        if c.Left != nil && c.Val != c.Left.Val {
            l = -1
        }
        if c.Right != nil && c.Val != c.Right.Val {
            r = -1
        }
        ans = max(ans, l + r + 2)
        return max(l, r) + 1
    }
    dfs(root)
    return
}

124. 二叉树中的最大路径和

题目求的是,因此不必从叶子节点出发,所以需要加上一个 \(max\) 判断。

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func maxPathSum(root *TreeNode) int {
    ans := math.MinInt
    var dfs func(*TreeNode) int
    dfs = func(c *TreeNode) int {
        if c == nil {
            return 0
        }
        l, r := max(0, dfs(c.Left)), max(0, dfs(c.Right))
        ans = max(ans, l + r + c.Val)
        return max(l, r) + c.Val
    }
    dfs(root)
    return ans
}

2385. 感染二叉树需要的总时间

// 三种情况:
// 1. 最长路径在 start 节点的左子树
// 2. 最长路径在 start 节点的右子树
// 3. 最长路径经过 start 的父节点
// 归纳成两种:
// 1. start 为根节点的最长子树直径
// 2. start 为叶子节点的最长树直径
func amountOfTime(root *TreeNode, start int) (ans int) {
    var dfs func(*TreeNode) (int, bool)
    dfs = func(c *TreeNode) (int, bool) {
        if c == nil {
            return 0, false
        }
        l, isL := dfs(c.Left) 
        r, isR := dfs(c.Right)
        if c.Val == start {
            // 当前节点是 start,计算子树最长直径
            ans = max(ans, l, r)
            // 已经找到了 start,返回 1 表示把 start 的子树删除
            return 1, true
        }
        if isL || isR {
            ans = max(ans, l + r)
            if isL {
                return l + 1, true
            }
            return r + 1, true
        }
        return max(l, r) + 1, false
    }
    dfs(root)
    return 
}

236. 二叉树的最近公共祖先

func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
    if root == nil || root == p || root == q {
        return root
    }

    left := lowestCommonAncestor(root.Left, p, q)
    right := lowestCommonAncestor(root.Right, p, q)
    if left == nil {
        return right
    }
    if right == nil {
        return left
    }
    return root
}

235. 二叉搜索树的最近公共祖先

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val   int
 *     Left  *TreeNode
 *     Right *TreeNode
 * }
 */
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
    if root.Val > p.Val && root.Val > q.Val {
        return lowestCommonAncestor(root.Left, p, q)
    }
    if root.Val < p.Val && root.Val < q.Val {
        return lowestCommonAncestor(root.Right, p, q)
    }
    return root
}

1123. 最深叶节点的最近公共祖先

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func depth(root *TreeNode) int {
    if root == nil {
        return 0
    }
    l, r := depth(root.Left), depth(root.Right)
    return max(l, r) + 1
}
func lcaDeepestLeaves(root *TreeNode) *TreeNode {
    if root == nil {
        return nil
    } 
    l, r := depth(root.Left), depth(root.Right)
    if l == r {
        return root
    } else if l > r {
        return lcaDeepestLeaves(root.Left)
    } else {
        return lcaDeepestLeaves(root.Right)
    }
}

102. 二叉树的层序遍历

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func levelOrder(root *TreeNode) (ans [][]int) {
    if root == nil {
        return [][]int{}
    }
    q := make([]*TreeNode, 0) 
    q = append(q, root)
    for len(q) > 0 {
        list := make([]int, 0)
        for t := len(q); t > 0; t-- {
            cur := q[0]
            q = q[1:]
            list = append(list, cur.Val)
            if cur.Left != nil {
                q = append(q, cur.Left)
            }
            if cur.Right != nil {
                q = append(q, cur.Right)
            }
        }
        ans = append(ans, list)
    }
    return
}

103. 二叉树的锯齿形层序遍历

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func zigzagLevelOrder(root *TreeNode) (ans [][]int) {
    if root == nil {
        return
    }
    q := make([]*TreeNode, 0) 
    q = append(q, root)
    for len(q) > 0 {
        nxt := []*TreeNode{}
        vals := make([]int, len(q))
        for i, node := range q {
            if len(ans) % 2 > 0 {
                vals[len(q)-1-i] = node.Val
            } else {
                vals[i] = node.Val
            }
            if node.Left != nil {
                nxt = append(nxt, node.Left)
            }
            if node.Right != nil {
                nxt = append(nxt, node.Right)
            }
        }
        q = nxt
        ans = append(ans, vals)
    }
    return 
}

513. 找树左下角的值

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func findBottomLeftValue(root *TreeNode) (ans int) {
    cur := []*TreeNode{root}
    for len(cur) > 0 {
        nxt := []*TreeNode{}
        for i, node := range cur {
            if i == 0 {
                ans = node.Val
            }
            if node.Left != nil {
                nxt = append(nxt, node.Left)
            }
            if node.Right != nil {
                nxt = append(nxt, node.Right)
            }
        }
        cur = nxt
    }
    return 
}

515. 在每个树行中找最大值

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func largestValues(root *TreeNode) (ans []int) {
    if root == nil {
        return
    }
    cur := []*TreeNode{root}
    for len(cur) > 0 {
        nxt := []*TreeNode{}
        mx := math.MinInt
        for _, node := range cur {
            mx = max(mx, node.Val)
            if node.Left != nil {
                nxt = append(nxt, node.Left)
            }
            if node.Right != nil {
                nxt = append(nxt, node.Right)
            }
        }
        cur = nxt
        ans = append(ans, mx)
    }
    return
}

1376. 通知所有员工所需的时间

自顶向上,自底向下都能做

func numOfMinutes(n int, headID int, manager []int, informTime []int) int {
    g := make([][]int, n)
    for u, v := range manager {
        if v != -1 {
            g[v] = append(g[v], u)
        }
    }
    var dfs func(int) int
    dfs = func(i int) int {
        ret := 0
        for _, v := range g[i] {
            ret = max(ret, dfs(v))
        }
        return ret + informTime[i]
    }
    return dfs(headID)
}

1443. 收集树上所有苹果的最少时间

func minTime(n int, edges [][]int, hasApple []bool) int {
    g := make([][]int, n)
    for _, edge := range edges {
        u, v := edge[0], edge[1]
        g[u] = append(g[u], v)
        g[v] = append(g[v], u)
    }
    var dfs func(int, int) int
    dfs = func(u, fa int) int {
        ret := 0
        for _, v := range g[u] {
            if v == fa {
                continue
            }
            ret += dfs(v, u)
        }

        if u != 0 && (hasApple[u] || ret > 0) {
            ret += 2
        }
        return ret
    }
    return dfs(0, -1)
}

1377. T 秒后青蛙的位置

根据题意,青蛙只能一路向下。如果当前节点有 \(c\) 个子节点,那么跳到其中一个的概率是 \(\frac{1}{c}\)。因此答案可以看做是由若干分子为 \(1\) 的分数相乘得到,那么我们可以只计算分母,最后计算倒数。如果青蛙跳到了叶子节点,那么它会停留在叶子节点上。

func frogPosition(n int, edges [][]int, t int, target int) float64 {
    g := make([][]int, n + 1) 
    g[1] = []int{0}
    for _, edge := range edges {
        u, v := edge[0], edge[1]
        g[u] = append(g[u], v)
        g[v] = append(g[v], u)
    }
    ans := float64(0)
    var dfs func(int, int, int, int) bool
    dfs = func(i, fa, prod, time int) bool {
        if i == target && (time == 0 || len(g[i]) == 1) {
            ans = 1 / float64(prod)
            return true
        }
        if i == target || time == 0 {
            return false
        }
        for _, j := range g[i] {
            if j == fa {
                continue
            }
            if dfs(j, i, prod*(len(g[i]) - 1), time - 1) {
                return true
            }
        }
        return false
    }
    dfs(1, 0, 1, t)
    return ans
}

1161. 最大层内元素和

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func maxLevelSum(root *TreeNode) (ans int) {
    cur := []*TreeNode{root}
    ans = 1
    mx, level := root.Val, 1
    for len(cur) > 0 {
        nxt := []*TreeNode{}
        sum := 0
        for _, node := range cur {
            sum += node.Val
            if node.Left != nil {
                nxt = append(nxt, node.Left)
            }
            if node.Right != nil {
                nxt = append(nxt, node.Right)
            }
        }
        if sum > mx {
            mx = sum
            ans = level
        }
        level++
        cur = nxt
    } 
    return 
}

993. 二叉树的堂兄弟节点

dfs 记录当前节点,当前节点的父节点,当前节点的深度。如果之前找到了就做对比,没找到就记录。

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isCousins(root *TreeNode, x int, y int) bool {
    depth := 0
    var father *TreeNode
    var dfs func(*TreeNode, *TreeNode, int) bool
    dfs = func(cur, fa *TreeNode, d int) bool {
        if cur == nil {
            return false
        }
        if cur.Val == x || cur.Val == y {
            if depth > 0 {
                return depth == d && fa != father
            }
            // 之前没找到
            depth, father = d, fa
        }
        return dfs(cur.Left, cur, d + 1) || dfs(cur.Right, cur, d + 1)
    }
    return dfs(root, nil, 1)
}

2583. 二叉树中的第 K 大层和

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func kthLargestLevelSum(root *TreeNode, k int) int64 {
    cur := []*TreeNode{root}
    s := []int64{}
    for len(cur) > 0 {
        nxt := []*TreeNode{}
        sum := int64(0)
        for _, node := range cur {
            sum += int64(node.Val)
            if node.Left != nil {
                nxt = append(nxt, node.Left)
            }
            if node.Right != nil {
                nxt = append(nxt, node.Right)
            }
        }
        cur = nxt
        s = append(s, sum)
    } 
    if len(s) < k {
        return -1
    }
    slices.Sort(s)
    return s[len(s)-k]
}

1302. 层数最深叶子节点的和

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func deepestLeavesSum(root *TreeNode) (ans int) {
    cur := []*TreeNode{root}
    for len(cur) > 0 {
        nxt := []*TreeNode{}
        sum := 0
        for _, node := range cur {
            sum += node.Val
            if node.Left != nil {
                nxt = append(nxt, node.Left)
            }
            if node.Right != nil {
                nxt = append(nxt, node.Right)
            }
        }
        cur = nxt
        ans = sum
    }
    return
}
  1. 1. 题单
    1. 1.1. 遍历二叉树
    2. 1.2. 自顶向下 DFS
    3. 1.3. 自底向上 DFS
    4. 1.4. 树的直径
    5. 1.5. 最近公共祖先(LCA)
    6. 1.6. BFS
  2. 2. 题解
    1. 2.1. 144. 二叉树的前序遍历
    2. 2.2. 94. 二叉树的中序遍历
    3. 2.3. 145. 二叉树的后序遍历
    4. 2.4. 872. 叶子相似的树
    5. 2.5. 404. 左叶子之和
    6. 2.6. 671. 二叉树中第二小的节点
    7. 2.7. 104. 二叉树的最大深度
    8. 2.8. 111. 二叉树的最小深度
    9. 2.9. 112. 路径总和
    10. 2.10. 129. 求根节点到叶节点数字之和
    11. 2.11. 199. 二叉树的右视图
    12. 2.12. 1457. 二叉树中的伪回文路径
    13. 2.13. 1315. 祖父节点值为偶数的节点和
    14. 2.14. 988. 从叶结点开始的最小字符串
    15. 2.15. 1026. 节点与其祖先之间的最大差值
    16. 2.16. 1022. 从根到叶的二进制数之和
    17. 2.17. 623. 在二叉树中增加一行
    18. 2.18. 1372. 二叉树中的最长交错路径
    19. 2.19. 971. 翻转二叉树以匹配先序遍历
    20. 2.20. 965. 单值二叉树
    21. 2.21. 100. 相同的树
    22. 2.22. 101. 对称二叉树
    23. 2.23. 951. 翻转等价二叉树
    24. 2.24. 110. 平衡二叉树
    25. 2.25. 226. 翻转二叉树
    26. 2.26. 617. 合并二叉树
    27. 2.27. 2331. 计算布尔二叉树的值
    28. 2.28. 508. 出现次数最多的子树元素和
    29. 2.29. 563. 二叉树的坡度
    30. 2.30. 606. 根据二叉树创建字符串
    31. 2.31. 2265. 统计值等于子树平均值的节点数
    32. 2.32. 1339. 分裂二叉树的最大乘积
    33. 2.33. 1145. 二叉树着色游戏
    34. 2.34. 572. 另一棵树的子树
    35. 2.35. 1530. 好叶子节点对的数量
    36. 2.36. 814. 二叉树剪枝
    37. 2.37. 1325. 删除给定值的叶子节点
    38. 2.38. 1110. 删点成林
    39. 2.39. 543. 二叉树的直径
    40. 2.40. 687. 最长同值路径
    41. 2.41. 124. 二叉树中的最大路径和
    42. 2.42. 2385. 感染二叉树需要的总时间
    43. 2.43. 236. 二叉树的最近公共祖先
    44. 2.44. 235. 二叉搜索树的最近公共祖先
    45. 2.45. 1123. 最深叶节点的最近公共祖先
    46. 2.46. 102. 二叉树的层序遍历
    47. 2.47. 103. 二叉树的锯齿形层序遍历
    48. 2.48. 513. 找树左下角的值
    49. 2.49. 515. 在每个树行中找最大值
    50. 2.50. 1376. 通知所有员工所需的时间
    51. 2.51. 1443. 收集树上所有苹果的最少时间
    52. 2.52. 1377. T 秒后青蛙的位置
    53. 2.53. 1161. 最大层内元素和
    54. 2.54. 993. 二叉树的堂兄弟节点
    55. 2.55. 2583. 二叉树中的第 K 大层和
    56. 2.56. 1302. 层数最深叶子节点的和