Last Stone Weight II
update 2020 Dec 1
We have a collection of rocks, each rock has a positive integer weight.
Each turn, we choose any two rocks 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 totally destroyed;
If x != y, the stone of weight x is totally destroyed, and the stone of weight y has new weight y-x.
At the end, there is at most 1 stone left. Return the smallest possible weight of this stone (the weight is 0 if there are no stones left.)
Example 1:
Input: [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.
Note:
1. 1 <= stones.length <= 30
2. 1 <= stones[i] <= 100
Basic Idea:
当两个石头相遇,如果重量相同,则抵消,否则生成一个两者重量相减的石头,求最后剩下一个石头的最小重量。
例如例子中的[2,7,4,1,8,1]
,我们经过分步相消,实际上过程是:(4-2)-(8-7)-1+1 = 4-2-8+7-1+1 = 1
。我们注意到实际上是把每个数字前面添上正号或者负号,求和使之和最小。这就将这道题转换为了另一道题 Partition Equal Subset Sum。我们只要将输入数组分成两个subset,一个附带正号,一个附带负号,分别求和并使两者和的差值最小即可。
仍然可以使用和那道题类似的DP思路,使用一个长度为 sum(nums) / 2 + 1
的 boolean dp 数组,其中 dp[i]
表示能否找到一个subset使得其sum等于i。最终需要返回两个subset和的差值的最小值,所以我们取dp数组中最大为true的i作为其中一个sum,另一个sum就是总和减去它,返回两个sum的差的绝对值即可。
Java Code
class Solution {
public int lastStoneWeightII(int[] stones) {
int sum = 0;
for (int num : stones) {
sum += num;
}
int target = sum / 2;
boolean dp[] = new boolean[target + 1];
dp[0] = true;
int maxPossibleSum = 0;
for (int num : stones) {
// 从大到小,避免前面的计算影响后面的结果
for (int i = target - num; i >= 0; --i) {
if (dp[i]) {
dp[i + num] = true;
maxPossibleSum = Math.max(maxPossibleSum, i + num);
}
}
}
return sum - maxPossibleSum - maxPossibleSum;
}
}
Last updated