leetcode
leetcode 2851 ~ 2900
二叉树染色

二叉树染色

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 324 ms, 内存: 22.6 MB


/*
 * Problem: Given a binary tree with a root node, where each node has a value and is initially white. You can color nodes with blue dye.
 * You need to ensure that the maximum number of blue connected nodes does not exceed k. Find the maximum sum of the values of the blue nodes.
 * 
 * Approach using Java Streams:
 * 1. Define a TreeNode class to represent nodes in the binary tree.
 * 2. Implement a recursive function using streams to traverse and process the tree.
 */

import java.util.Arrays;
import java.util.stream.IntStream;

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

public class Solution {
    public int maxBlueNodesValue(TreeNode root, int k) {
        return dfs(root, k)[0];
    }

    private int[] dfs(TreeNode node, int k) {
        if (node == null) return new int[k + 1];

        int[] left = dfs(node.left, k);
        int[] right = dfs(node.right, k);

        int[] dp = new int[k + 1];

        // If we don't color the current node
        IntStream.range(0, k + 1).forEach(i -> dp[0] = Math.max(dp[0], left[i] + right[i]));

        // If we color the current node
        IntStream.range(1, k + 1).forEach(i -> {
            IntStream.range(0, i).forEach(j -> dp[i] = Math.max(dp[i], node.val + left[j] + right[i - 1 - j]));
        });

        return dp;
    }
}

解释

方法:

该题解采用递归方法进行动态规划。首先定义一个辅助函数 maxSubTree,该函数返回一个列表,其中包含以当前节点为根的子树内,各个可能的蓝色节点群组的最大值累计。列表中的每个位置i表示恰好有i个连续节点被染色的情况下,可以获得的最大价值。函数首先处理基本情况,如果当前节点为空,则返回一个只包含0的列表。然后,它递归地计算左右子树的最大价值列表。使用两层循环遍历左右子树返回的列表,来确定在当前节点下,形成不同大小的蓝色节点群组的最大价值。外层循环和内层循环分别遍历左子树和右子树返回的列表,通过将左右子树的某些价值组合并加上当前节点的价值,来更新结果列表。最后,返回整棵树调用 maxSubTree 后的最大价值。

时间复杂度:

O(n*k^2)

空间复杂度:

O(n*k)

代码细节讲解

🦆
在递归函数`maxSubTree`中,当节点为null时返回的是包含一个0的列表,这里的0代表什么意义?
在递归函数`maxSubTree`中,当节点为null时返回包含一个0的列表,这里的0代表的是,在没有任何节点的情况下,染色节点个数为0时的最大价值。因为没有节点可染色,所以最大价值是0。这个返回值为递归处理提供了一个基准情况,确保当递归到空节点时,可以正常地继续计算而不会出现错误或异常。
🦆
你在计算`res[0]`时使用了`l[-1] + r[-1]`,这个操作代表的是什么?为什么选择列表的最后一个元素进行相加?
在计算`res[0]`时使用`l[-1] + r[-1]`,这个操作代表的是计算当前节点不被染色时,其左右子树能够达到的最大价值的和。这里选择列表的最后一个元素进行相加是因为,列表的最后一个元素(即`l[k]`和`r[k]`)代表了在子树中恰好有k个连续节点被染成蓝色时的最大价值。因此,当当前节点不染色时,我们希望利用左右子树分别达到其最大染色潜力的和,这就是`l[-1]`和`r[-1]`的含义。
🦆
在更新`res`数组时,内层循环的终止条件为`k - i`,这里为什么要使用这个条件来限制循环的范围?
在更新`res`数组时,内层循环的终止条件设置为`k - i`是为了确保总的染色节点数不超过k。这里`i`表示从左子树中选取的染色节点数,而`j`表示从右子树中选取的染色节点数。因此,`i + j + 1`(加1表示当前节点也被染色)是当前节点下形成的蓝色节点群组的总数,这个值必须小于等于k。通过设置循环的终止条件为`k - i`,我们确保了在任何时候,左子树和右子树中选取的节点数之和不会超过k减去已选择的左子树节点数,从而保证整个节点群组的大小符合要求。

相关问题