此题可以转化成01背包问题,把数组的数组分成两部分,使两部分的值相等,各位数组值总和sum的一半,就是说从这个数组能不能凑出来一组数据的和为sum的一半,如果可以那么剩下来的值就可以凑出来另外一半。凑出一半总和的想法就是01背包了
class Solution {
public boolean canPartition(int[] nums) {
/**
1、确定状态与选择
i:代表物品的重量,也就是数组中的数值
w:背包的容量,从0到数组总和一半的值
2、定义dp数组
boolean[][] dp
dp[i][j] :前n物品可以放满背包容量为j时值为true
最终返回的是dp[nums.length][sum/2]
3、初始化条件
dp[i][0] = true
dp[0][j] = false;
4、状态转移逻辑
对于第i个物品
如果nums[i] > w ,即物品重量大于背包容量
不能放入背包,dp[i][j] = dp[i-1][j]
否则,说明该物品可以放入背包,那么有两种选择放或者不放,
dp[i][j] = dp[i][j-1] || dp[i-1][j- nums[i]]
*/
int n = nums.length;
int sum = 0;
int max = 0;
for(int i =0;i<nums.length;i++){
max = Math.max(max,nums[i]);
sum += nums[i];
}
if(sum%2!=0){
return false;
}
if(max > sum/2){
return false;
}
sum /=2;
//定义dp数组
boolean[][] dp = new boolean[n+1][sum+1];
//初始化
for(int i=0;i<=sum;i++){
dp[0][i] =false;
}
for(int i=0;i<=n;i++){
dp[i][0] =true;
}
for(int i = 1;i<=n;i++){
for(int j =1;j<=sum;j++){
if(nums[i-1] > j){
dp[i][j] = dp[i-1][j];
}else {
dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i-1]];
}
}
}
return dp[n][sum];
}
}
一下是改造之后状态压缩的代码,用一个一维数组替代二维,因为在状态转移是被使用的总是当前行和上一行数据,所以从数组后面遍历,不断地向前覆盖数据即可,这样既节省了空间,又避免了数据冲突
class Solution {
public boolean canPartition(int[] nums) {
/**
1、确定状态与选择
i:代表物品的价值,也就是数组中的数值
w:背包的容量,从0到数组总和一半的值
2、定义dp数组
boolean[][] dp
dp[i][j] :前n物品可以放满背包容量为j时值为true
最终返回的是dp[nums.length][sum/2]
3、初始化条件
dp[i][0] = true
dp[0][j] = false;
4、状态转移逻辑
对于第i个物品
如果nums[i] > w ,即物品重量大于背包容量
不能放入背包,dp[i][j] = dp[i-1][j]
否则,说明该物品可以放入背包,那么有两种选择放或者不放,
dp[i][j] = dp[i][j-1] || dp[i-1][j- nums[i]]
*/
int n = nums.length;
int sum = 0;
int max = 0;
for(int i =0;i<nums.length;i++){
max = Math.max(max,nums[i]);
sum += nums[i];
}
if(sum%2!=0){
return false;
}
if(max > sum/2){
return false;
}
sum /=2;
//定义dp数组
boolean[] dp = new boolean[sum+1];
// boolean[][] dp = new boolean[n+1][sum+1];
//初始化
// for(int i=0;i<=sum;i++){
// dp[0][i] =false;
// }
// for(int i=0;i<=n;i++){
// dp[i][0] =true;
// }
dp[0] = true;
for(int i = 1;i<=n;i++){
for(int j =sum;j>0;j--){
// if(nums[i-1] > j){
// dp[i][j] = dp[i-1][j];
// }else {
// dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i-1]];
// }
if(nums[i-1] <= j){
dp[j] = dp[j] || dp[j-nums[i-1]];
}
}
}
return dp[sum];
}
}