思路:本题可以看成是0-1背包问题,给一个可装载重量为 sum / 2 的背包和 N 个物品,每个物品的重量记录在 nums 数组中,问是否在一种装法,能够恰好将背包装满?dp[i][j]表示前i个物品是否能装满容积为j的背包,当dp[i][j]为true时表示恰好可以装满。每个数都有放入背包和不放入两种情况,分析方法和0-1背包问题一样。 复杂度:时间复杂度O(n*sum)
,n是nums数组长度,sum是nums数组元素的和。空间复杂度O(n * sum),状态压缩之后是O(sum)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| public class Solution { public boolean canPartition(int[] nums) { int len = nums.length; int sum = 0; for (int num : nums) { sum += num; } if ((sum & 1) == 1) { return false; }
int target = sum / 2; boolean[][] dp = new boolean[len][target + 1]; for (int i = 0; i < n; i++) { dp[i][0] = true; } if (nums[0] <= target) { dp[0][nums[0]] = true; } for (int i = 1; i < len; i++) { for (int j = 0; j <= target; j++) { if (nums[i] <= j) { dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i]]; } else { dp[i][j] = dp[i - 1][j]; } }
if (dp[i][target]) { return true; } } return dp[len - 1][target]; } }
public class Solution {
public boolean canPartition(int[] nums) { int len = nums.length; int sum = 0; for (int num : nums) { sum += num; } if ((sum & 1) == 1) { return false; }
int target = sum / 2; boolean[] dp = new boolean[target + 1]; dp[0] = true;
if (nums[0] <= target) { dp[nums[0]] = true; } for (int i = 1; i < len; i++) { for (int j = target; nums[i] <= j; j--) { if (dp[target]) { return true; } dp[j] = dp[j] || dp[j - nums[i]]; } } return dp[target]; } }
|
参考文章