1049. Last Stone Weight II
You are given an array of integers stones where stones[i] is the weight of the ith 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 weightxis destroyed, and the stone of weightyhas 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.
题目解析:
- 尽量把石头分成重量均匀的两堆,这样最后碰撞剩余的重量最小。所以问题转化为容量为总重量一般的背包最多能装多少石头
代码:
class Solution {
public int lastStoneWeightII(int[] stones) {
if (stones.length == 1) return stones[0];
int sum = Arrays.stream(stones).sum();
int half = sum / 2;
int[] dp = new int[half+1];
dp[0] = 0;
for (int stone: stones) {
for (int i = half; i > 0; i--) {
if (i-stone >= 0) {
dp[i] = Math.max(dp[i], dp[i-stone] + stone);
}
}
}
return sum - dp[half] - dp[half];
}
}
494. Target Sum
You are given an integer array nums and an integer target.
You want to build an expression out of nums by adding one of the symbols '+' and '-' before each integer in nums and then concatenate all the integers.
- For example, if
nums = [2, 1], you can add a'+'before2and a'-'before1and concatenate them to build the expression"+2-1".
Return the number of different expressions that you can build, which evaluates to target.
题目解析:
- 类似的思路,把数组分为两堆,一堆全为+, 另一堆全为-, 这样两堆之和为sum,两堆之差就为target
left + right = sum; left - right = target => left = (sum +target) / 2
代码:
class Solution {
public int findTargetSumWays(int[] nums, int target) {
// + : left, - : right
// left + right = sum; left - right = target => left = (sum +target) / 2
int sum = Arrays.stream(nums).sum();
if (sum + target < 0 || (sum + target) % 2 != 0) return 0;
int left = (sum + target) / 2;
int[] dp = new int[left+1];
dp[0] = 1;
for (int num : nums) {
for (int i = left; i >= num; i--) {
dp[i] += dp[i-num];
}
}
return dp[left];
}
}
474. Ones and Zeroes
You are given an array of binary strings strs and two integers m and n.
Return the size of the largest subset of strs such that there are at most m **0 's and n **1 's in the subset.
A set x is a subset of a set y if all elements of x are also elements of y.
题目解析:
- 两个维度的01背包
代码:
class Solution {
public int findMaxForm(String[] strs, int m, int n) {
int[][] dp = new int[m+1][n+1];
for (int k = 0; k < strs.length; k++) {
int one = 0, zero = 0;
for (int i = 0; i < strs[k].length(); i++) {
if (strs[k].charAt(i) == '0') zero++;
if (strs[k].charAt(i) == '1') one++;
}
for (int i = m; i >= zero; i--) {
for (int j = n; j >= one; j--) {
dp[i][j] = Math.max(dp[i][j], dp[i-zero][j-one] + 1);
}
}
}
return dp[m][n];
}
}
总结
- 01背包从后往前遍历