刷题顺序按照代码随想录建议
题目描述
英文版描述
You are given an array of integers stones
where stones[i]
is the weight of the i(th)
stone.
We are playing a game with the stones. On each turn, we choose any two stones and smash them together. Suppose the stones have weights x
and y
with x <= y
. The result of this smash is:
- If
x == y
, both stones are destroyed, and - If
x != y
, the stone of weightx
is destroyed, and the stone of weighty
has new weighty - x
.
At the end of the game, there is at most one stone left.
Return the smallest possible weight of the left stone . If there are no stones left, return 0
.
Example 1:
Input: stones = [2,7,4,1,8,1] Output: 1 Explanation: We can combine 2 and 4 to get 2, so the array converts to [2,7,1,8,1] then, we can combine 7 and 8 to get 1, so the array converts to [2,1,1,1] then, we can combine 2 and 1 to get 1, so the array converts to [1,1,1] then, we can combine 1 and 1 to get 0, so the array converts to [1], then that's the optimal value.
Example 2:
Input: stones = [31,26,33,21,40] Output: 5
Constraints:
1 <= stones.length <= 30
1 <= stones[i] <= 100
英文版地址
中文版描述
有一堆石头,用整数数组 stones
表示。其中 stones[i]
表示第 i
块石头的重量。
每一回合,从中选出任意两块石头 ,然后将它们一起粉碎。假设石头的重量分别为 x
和 y
,且 x <= y
。那么粉碎的可能结果如下:
- 如果
x == y
,那么两块石头都会被完全粉碎; - 如果
x != y
,那么重量为x
的石头将会完全粉碎,而重量为y
的石头新重量为y-x
。
最后,最多只会剩下一块 石头。返回此石头 最小的可能重量 。如果没有石头剩下,就返回 0
。
示例 1:
输入: stones = [2,7,4,1,8,1] 输出: 1 解释: 组合 2 和 4,得到 2,所以数组转化为 [2,7,1,8,1], 组合 7 和 8,得到 1,所以数组转化为 [2,1,1,1], 组合 2 和 1,得到 1,所以数组转化为 [1,1,1], 组合 1 和 1,得到 0,所以数组转化为 [1],这就是最优值。
示例 2:
输入: stones = [31,26,33,21,40] 输出: 5
提示:
1 <= stones.length <= 30
1 <= stones[i] <= 100
中文版地址
解题方法
动态规划
java
class Solution {
public int lastStoneWeightII(int[] stones) {
int sum = 0;
for (int i = 0; i < stones.length; i++) {
sum += stones[i];
}
int target = sum / 2;
// 1. 确定dp数组含义:dp[row][col] 表示任选[0,row]中的石头(每个石头最多选一次)放入容积为col的背包,总价值为dp[row][col]
int[][] dp = new int[stones.length][target + 1];
// 2. 初始化dp数组(第一行)
for (int i = 0; i < target + 1; i++) {
if (i >= stones[0]) {
dp[0][i] = stones[0];
}
}
// 3. 确定遍历顺序
for (int row = 1; row < stones.length; row++) {
for (int col = 0; col < target + 1; col++) {
// 4. 确定递推公式
if (col < stones[row]) {
dp[row][col] = dp[row - 1][col];
} else {
dp[row][col] = Math.max(dp[row - 1][col], dp[row - 1][col - stones[row]] + stones[row]);
}
}
}
return sum - dp[stones.length - 1][target] - dp[stones.length - 1][target];
}
}
复杂度分析
- 时间复杂度:O(n^2),其中n是数组长度
- 空间复杂度:O(n*target),其中n是数组长度,target 是整个数组的元素和的一半