LC每日一题|20240424 - 2385. 感染二叉树需要的总时间

5 阅读2分钟

LC每日一题|20240424 - 2385. 感染二叉树需要的总时间

给你一棵二叉树的根节点 root ,二叉树中节点的值 互不相同 。另给你一个整数 start 。在第 0 分钟,感染 将会从值为 start 的节点开始爆发。

每分钟,如果节点满足以下全部条件,就会被感染:

  • 节点此前还没有感染。
  • 节点与一个已感染节点相邻。

返回感染整棵树需要的分钟数

提示:

  • 树中节点的数目在范围 [1, 10^5]
  • 1 <= Node.val <= 10^5
  • 每个节点的值 互不相同
  • 树中必定存在值为 start 的节点

题目等级:Medium

解题思路

不难发现此题的难点是在如何处理 start 节点的 parents 。我们首先可以找到 start 节点,然后记录它的 parent 节点们到它的距离,显然dfs是更适合需求的方案。对于其他的节点,我们可以先定义距离为无歧义的 -1 ,待下一次遍历时进行处理。

由于题目并没有要求我们不能改动树,所以我们可以将这个距离值保存在root.val中。

下一步,我们可以使用bfs再次遍历整棵树。对于上一步中未处理的节点,其距离值为其父节点的距离值+1。然后在遍历的过程中统计最大值返回。

AC代码

/**
 * Example:
 * var ti = TreeNode(5)
 * var v = ti.`val`
 * Definition for a binary tree node.
 * class TreeNode(var `val`: Int) {
 *     var left: TreeNode? = null
 *     var right: TreeNode? = null
 * }
 */
class Solution {
    fun amountOfTime(root: TreeNode, start: Int): Int {
        dfs(root, start) 
        var max = root.`val`
        val queue = ArrayDeque<TreeNode>()
        queue.addLast(root)
        while (queue.isNotEmpty()) {
            repeat(queue.size) {
                val node = queue.removeFirst()
                node.left?.let {
                    if (it.`val` == -1) it.`val` = node.`val` + 1
                    max = Math.max(it.`val`, max)
                    queue.addLast(it)
                }
                node.right?.let {
                    if (it.`val` == -1) it.`val` = node.`val` + 1
                    max = Math.max(it.`val`, max)
                    queue.addLast(it)
                }
            }
        }
        return max
    }

    fun dfs(root: TreeNode?, target: Int): Int {
        if (root == null) return -1
        val left = dfs(root.left, target)
        val right = dfs(root.right, target)
        root.`val` = if (root.`val` == target) 0 else if (left >= 0 || right >= 0) Math.max(left, right) + 1 else -1
        return root.`val`
    }
}

时间复杂度:O(n),需要两次遍历。

空间复杂度:O(n)