代码
- 背包问题
dp[i][j] 表示从数组[0,i]中选择若干个,可以是0个,是否存在一种选取方案 使得和为j
对于num[i]选或者不选- 为什么要一个一个选物品,容量也一点点增加(为什么用两个for循环)
根据dp含义:最终想要得到dp[len-1][target]
已知可以初始化的有dp[i][0]=true、dp[0][nums[0]]=true
需要通过状态转移程dp[i][j]=dp[i-1][j]||dp[i-1] (遍历i) [j-nums[i](遍历j)];
逐步得到
class Solution {
public boolean canPartition(int[] nums) {
int len=nums.length;
//计算false的情况
int sum=0;
int maxnum=0;
for(int i=0;i<len;i++){
sum+=nums[i];
maxnum=Math.max(maxnum,nums[i]);
}
if(sum%2!=0){
return false;
}
int target=sum/2;
if(maxnum>target){
return false;
}
boolean[][] dp=new boolean[len][target+1];
//边界条件
//j==0的时候,所有的dp[i][0]都为true ,从前i个中选0个得到0
//i=0的时候,dp[0][nums[0]] 在前1个数里面选择一个数,和为nums[0] 为true
for(int i=0;i<len;i++){
dp[i][0]=true;
}
dp[0][nums[0]]=true;
for(int i=1;i<len;i++){
for(int j=1;j<=target;j++){
if(nums[i]<=j){
dp[i][j]=dp[i-1][j]||dp[i-1][j-nums[i]];
//nums[i]符合要求 可选可不选
//dp[i-1][j-nums[i]] 选了nums[i]————所以要看看前i-1个有无和为j-nums[i]的存在
//dp[i-1][j] 不选nums[i]———— 所以要看看有前i-1个有无和为j-nums[i]的
}
else {
//num[i]不符合要求不选
dp[i][j]=dp[i-1][j];
}
}
}
return dp[len-1][target];
}
}