1049. Last Stone Weight II
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 weightx
is totally destroyed, and the stone of weighty
has new weighty-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.
Solution
This question can be reduced to find the maximun sum of stones in which the sum can be only less or equal to totalSum/2:
S2 - S1 = diff
S1 + S2 = totalS
diff = totalSum - 2*S1
Thus if we want the diff to be the smallest one, S1 must be the max one in range (0~totalSum/2)
To find the maximum S1, it is similar to 494. Target Sum
dp[i][j] denotes if it is possible to use the first jth elements to get a sum value i
public int lastStoneWeightII(int[] stones) {
int S = 0, S2 = 0;
for (int s : stones) S += s;
int n = stones.length;
boolean[][] dp = new boolean[S + 1][n + 1];
for (int i = 0; i <= n; i++) {
dp[0][i] = true;
}
for (int i = 1; i <= n; i++) {
for (int s = 1; s <= S / 2; s++) {
if (dp[s][i - 1] || (s >= stones[i - 1] && dp[s - stones[i - 1]][i - 1])) {
dp[s][i] = true;
S2 = Math.max(S2, s);
}
}
}
return S - 2 * S2;
}
Last updated
Was this helpful?