题目链接
题目描述
解题思路
可以看成是背包问题:从n个物品中选取m个物品,每个物品只能选择一次,每个物品的价值对应p,是否能恰好选出价值和为k的选法;
记dp[i][j] 表示 是否能从前i个物品中恰好选择价值和为j的选法;对于每个物品而言,只有两种情况:选和不选,因此状态转移方程为:
if(当前物品i价值 > j) {
// 不选择i,往前走
dp[i][j] = dp[i-1][j];
} else{
// 选择i,往前走 | 不选择i,往前走 两者都可以进行判断取或
dp[i][j] = dp[i-1][j] | dp[i-1][j-1];
}
实现代码:
class Solution {
public boolean canPartition(int[] nums) {
int len = nums.length;
int sum = nums[0];
int max = sum;
for (int i = 1; i < len; i++) {
sum += nums[i];
max = max > nums[i] ? max : nums[i];
}
if (sum % 2 != 0) {
return false;
}
int target = sum / 2;
if (target < max) {
return false;
}
boolean[][] dp = new boolean[len][target + 1];
for (int i = 0; i < len; i++) {
dp[i][0] = true;
}
dp[0][nums[0]] = true;
for (int i = 1; i < len; i++) {
int val = nums[i];
for (int j = 1; j <= target; j++) {
if (j >= val) {
dp[i][j] = dp[i - 1][j - val] || dp[i - 1][j];
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[len - 1][target];
}
}