石子游戏 VII
难度:
标签:
题目描述
代码结果
运行时间: 610 ms, 内存: 16.0 MB
/*
题目思路:
1. 使用动态规划来解决这个问题。
2. dp[i][j] 表示从 i 到 j 的石子数组中,当前玩家与另一个玩家得分差的最大值。
3. 如果当前玩家选择左边的石子,得分差为 stones[i] - dp[i+1][j]。
4. 如果当前玩家选择右边的石子,得分差为 stones[j] - dp[i][j-1]。
5. 转移方程为 dp[i][j] = max(stones[i] - dp[i+1][j], stones[j] - dp[i][j-1])。
6. 最终结果为 dp[0][n-1]。
*/
import java.util.stream.IntStream;
public int stoneGameVII(int[] stones) {
int n = stones.length;
int[][] dp = new int[n][n];
int[] prefixSum = IntStream.range(0, n + 1).map(i -> i == 0 ? 0 : IntStream.range(0, i).map(j -> stones[j]).sum()).toArray();
IntStream.range(1, n).forEach(length ->
IntStream.range(0, n - length).forEach(i -> {
int j = i + length;
int sum = prefixSum[j + 1] - prefixSum[i];
dp[i][j] = Math.max(sum - stones[i] - dp[i + 1][j], sum - stones[j] - dp[i][j - 1]);
})
);
return dp[0][n - 1];
}
解释
方法:
该题解采用了动态规划的方法。dp[i] 表示从石头 i 到当前考虑的石头 j 的区间内,当前玩家与另一玩家的得分差的最大值。在每一轮中,玩家可以选择移除最左边或最右边的石头,然后更新 dp[i] 为剩余石头的总和减去 dp[i+1](如果移除左边石头)和 dp[i](如果移除右边石头)中的较大值,以保持得分差最大化。
时间复杂度:
O(n^2)
空间复杂度:
O(n)
代码细节讲解
🦆
在题解中,动态规划数组`dp`的初始值为`stones`数组本身,这种初始化方法的合理性何在?
▷🦆
题解中的动态规划状态转移方程`dp[i] = acc - (dp[i + 1] if dp[i + 1] > dp[i] else dp[i])`是如何确保当前玩家与对手的得分差最大化的?
▷🦆
题解示例实现中,最后返回的是`acc - dp[0]`,其中`acc`表示什么?为何最终的得分差是用这两者的差值来表示?
▷🦆
在动态规划解法中,为何要倒序更新`i`从`j-1`到`0`?直接正序更新有何不妥?
▷