今天都是难题,一个自己做出了的都没有
1049. 最后一块石头的重量 II
难在数学上没想到了
原理是将总的质量除以2作为背包的容量,然后用这个容量去装尽可能多的石头。
最后装进来的石头因为要抵消,所以乘以二再背总的质量减去即可代码如下:
public int lastStoneWeightII(int[] stones) {
if(stones.length==1)return stones[0];
int sum = 0;
for(int i=0;i<stones.length;i++){
sum+=stones[i];
}
int re = sum;
sum/=2;
int[] dp = new int[sum+1];
for(int i=0;i<stones.length;i++){
for(int j=sum;j>=stones[i];j--){
dp[j] = Math.max(dp[j],dp[j-stones[i]]+stones[i]);
}
}
return re-2*dp[sum];
}
494. 目标和
两种方法吧,第一中用回溯算法
这里有个细节,就是得全部取,所以不能用for代码如下:
int count = 0;
public int findTargetSumWays(int[] nums, int target) {
backTracking(nums,target,0,0);
return count;
}
public void backTracking(int[] nums, int target,int startIndex,int sum){
if(sum==target&&startIndex==nums.length){
count++;
return;
}
if(startIndex>=nums.length)return;
backTracking(nums,target,startIndex+1,sum+nums[startIndex]);
backTracking(nums,target,startIndex+1,sum-nums[startIndex]);
return;
}
第二种方法,动态规划:
思想是
如何转化为01背包问题呢。
假设加法的总和为x,那么减法对应的总和就是sum - x。
所以我们要求的是 x - (sum - x) = target
x = (target + sum) / 2
此时问题就转化为,装满容量为x的背包,有几种方法。
这里的x,就是bagSize,也就是我们后面要求的背包容量。
大家看到(target + sum) / 2 应该担心计算的过程中向下取整有没有影响。
代码如下:
public int findTargetSumWays(int[] nums, int target) {
int sum = 0;
for (int i = 0; i < nums.length; i++) sum += nums[i];
if ( target < 0 && sum < -target) return 0;
if ((target + sum) % 2 != 0) return 0;
int size = (target + sum) / 2;
if(size < 0) size = -size;
int[] dp = new int[size + 1];
dp[0] = 1;
for (int i = 0; i < nums.length; i++) {
for (int j = size; j >= nums[i]; j--) {
dp[j] += dp[j - nums[i]];
}
}
return dp[size];
}
474. 一和零
二维的基础动态规划问题代码如下:
public int findMaxForm(String[] strs, int m, int n) {
String tool;
int a = 0;
int b = 0;
int[][] dp = new int[m+1][n+1];
for(int i=0;i<strs.length;i++){
a = 0;
b = 0;
tool = strs[i];
for(int j=0;j<tool.length();j++){
if(tool.charAt(j)=='0'){
a++;
}
if(tool.charAt(j)=='1'){
b++;
}
}
for(int j=m;j>=a;j--){
for(int k=n;k>=b;k--){
dp[j][k] = Math.max(dp[j][k],dp[j-a][k-b]+1);
}
}
}
return dp[m][n];
}