1049.最后一块石头的重量II
文章
[代码随想录|1049.最后一块石头的重量]https://programmercarl.com/1049.%E6%9C%80%E5%90%8E%E4%B8%80%E5%9D%97%E7%9F%B3%E5%A4%B4%E7%9A%84%E9%87%8D%E9%87%8FII.html()
思路
石头分成两组,以总重量一半为背包容量,求最多容纳石头的重量为较小一组,从总重量中减去较小一组的重量为较大一组重量,两组重量只差即为所求。
代码
class Solution {
public int lastStoneWeightII(int[] stones) {
int sum = 0;
int i, j, n;
n = stones.length;
for (i = 0; i < n; ++i) {
sum += stones[i];
}
int capacity = sum >> 1;
int[] dp = new int[capacity + 1];
for (i = 0; i < capacity + 1; ++i) {
dp[i] = stones[0] > i ? 0 : stones[0];
}
for (i = 1; i < n; ++i) {
for (j = capacity; j > 0; --j) {
if (j >= stones[i]) {
dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]);
}
}
}
return sum - (dp[capacity] << 1);
}
}
494.目标和
文章
思路
分成两组,一组加号,另一组减号,加号组之和应为
s
u
m
+
t
a
r
g
e
t
2
\frac{sum+target}{2}
2sum+target,因此如果不整除则直接返回0
用dp数组,dp[i]表示加号组在当前求和正好为i的方案数
代码
class Solution {
public int findTargetSumWays(int[] nums, int target) {
int i, j, n, sum;
n = nums.length;
sum = 0;
for (i = 0; i < n; ++i) {
sum += nums[i];
}
if ((sum + target) % 2 != 0 || sum + target < 0) {
return 0;
}
int pos = sum + target >> 1;
int[] dp = new int[pos + 1];
for (j = 0; j < pos + 1; ++j) {
dp[j] = nums[0] == j ? 1 : 0;
}
dp[0] += 1;
for (i = 1; i < n; ++i) {
for (j = pos; j > -1; --j) {
if (j >= nums[i]) {
dp[j] += dp[j - nums[i]];
}
// if (j == pos)
// System.out.println(dp[j]);
}
}
return dp[pos];
}
}
474.一和零
文章
思路
不得不用二维数组了
dp[i][j]表示0和1数量分别限制为i和j时的最大子集规模
代码
class Solution {
public int findMaxForm(String[] strs, int m, int n) {
int i, j, k, num;
int nz, no;
num = strs.length;
int[][] dp = new int[m + 1][n + 1];
for (i = 0; i < num; ++i) {
nz = count(strs[i], '0');
no = count(strs[i], '1');
if (nz <= m && no <= n) {
for (j = m; j >= nz; --j) {
for (k = n; k >= no; --k) {
dp[j][k] = Math.max(dp[j - nz][k - no] + 1, dp[j][k]);
}
}
}
}
return dp[m][n];
}
public int count (String str, char tar) {
int res = 0;
char ch;
int i, n;
n = str.length();
for (i = 0; i < n; ++i) {
if (str.charAt(i) == tar) {
++res;
}
}
return res;
}
}
总结
二刷,还需熟练,小错误一堆