01背包问题的一维数组和二维的模板
1049.最后一块石头的重量II
讲的很好
最小可能重量:
1.剩余0,就可以看成两个完全相同的背包问题
2. 剩余不是0,要越小越好 = half(+) - half(-) ,这样就可以返回越小的值
从stone中选择石头,使得<=背包容量
1.二维数组
class Solution {
public int lastStoneWeightII(int[] stones) {
int n = stones.length;
int sum =0;
for(int stone:stones){
sum +=stone;
}
int half = sum>>1;
int[][] dp = new int[n+1][half+1];
for(int i=1;i<=n;i++) // 遍历商品
for(int j =1;j<=half;j++){ //背包容量
int cur =stones[i-1];
if( cur>j){ // 装不下
dp[i][j] = dp[i-1][j];
}else{
dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j- cur]+ cur);
}
}
return sum - (dp[n][half]<<1);
}
}
注意这里dp[i][j]的大小,都是n+1,和 half+1,
dp[i][j] ,表示第i个物品是否放入,对应的是stone[i-1]
2.一维数组
class Solution {
public int lastStoneWeightII(int[] stones) {
int n = stones.length;
int sum =0;
for(int stone:stones){
sum +=stone;
}
int half = sum>>1;
int[] dp = new int[half+1];
for(int i =0;i<n;i++){ // 从最开始的商品开始遍历
int cur = stones[i];
for(int j = half;j>=cur;j--){
dp[j] = Math.max(dp[j],dp[j-cur]+cur);
}
}
return sum -2*dp[half];
}
}
494. 目标和
转换为背包问题:
视频解析:
相当于将一个数组分成两部分,一部分前面加“+”,之和为
x
x
x,另一部分“ - ”,绝对值之和为
y
y
y
数组之和
s
u
m
sum
sum =
x
x
x +
y
y
y,
t
a
r
g
e
t
target
target =
x
x
x -
y
y
y,
x
x
x =
(
s
u
m
+
t
a
r
g
e
t
)
(sum+target)
(sum+target)/2
所以问题转换为: 一个背包容量为x,装满的方式有几种的问题了
class Solution {
public int findTargetSumWays(int[] nums, int target) {
int sum =0;
for(int num:nums){
sum += num;
}
if(sum<target||-sum>target || (sum+target)%2 != 0){
return 0;
}
int x = (sum+target)>>1;
int[] dp = new int[x+1];
dp[0] =1; //填满背包容器为0的方式只有1种
for(int i =0;i<nums.length;i++){
int cur = nums[i];
for(int j = x;j>= cur;j--){
dp[j] = dp[j] + dp[j-cur]; //有几种,就是选和不选,选就是dp[j-cur] ,不选就是dp[j]
}
}
return dp[x];
}
}
474. 一和零
这道题是多背包问题,所以就对应有三维数组和二维数组的两种方式
三维数组的方式:
主要还是以二维为主:
class Solution {
public int findMaxForm(String[] strs, int m, int n) {
int[][] dp = new int[m+1][n+1]; //1.dp[i][j] 分别表示在i放入0,j放入1的时候,最多的个数
//初始化
for(String str : strs){ //开始按照物品遍历
// 1.统计每个元素中0和1的个数
int zeros =0; int ones =0;
for(char ch: str.toCharArray()){
if(ch == '0'){
zeros++;
}else{
ones++;
}
}
//开始对当前物品装包
for(int i = m; i >= zeros; --i) {
for(int j = n; j >= ones; --j) {
dp[i][j] = Math.max(dp[i][j], dp[i - zeros][j - ones] + 1);
}
}
}
return dp[m][n];
}
}