Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal.
Note:
- Each of the array element will not exceed 100.
- The array size will not exceed 200.
Example 1:
Input: [1, 5, 11, 5] Output: true Explanation: The array can be partitioned as [1, 5, 5] and [11].
Example 2:
Input: [1, 2, 3, 5] Output: false Explanation: The array cannot be partitioned into equal sum subsets.
01背包问题 也就是一个array里面,能否背到sum / 2的重量;
dp[i][j]的物理意义是:我走到第i个物品,我是否取得j的重量;
class Solution {
public boolean canPartition(int[] nums) {
int totalsum = 0;
for(int num: nums) {
totalsum += num;
}
if(totalsum % 2 != 0) {
return false;
}
int n = nums.length;
boolean[][] dp = new boolean[n + 1][totalsum / 2 + 1];
// dp[i][j] , move ith position, whether or not i can get j amount;
dp[0][0] = true;
// 1st row;
for(int j = 1; j < dp[0].length; j++) {
dp[0][j] = false;
}
// 1st col;
for(int i = 1; i < dp.length; i++) {
dp[i][0] = true;
}
// calculate matrix;
for(int i = 1; i < dp.length; i++) {
for(int j = 1; j < dp[0].length; j++) {
dp[i][j] = dp[i - 1][j]; // not pick up;
if(j - nums[i - 1] >= 0) {
dp[i][j] |= dp[i - 1][j - nums[i - 1]];
}
}
}
return dp[n][totalsum / 2];
}
}
思路2:这题是 Partition to K Equal Sum Subsets 的简化版,如果用DFS暴力求,会超时,那么就需要用cache来加速;
dp[i][cursum] 代表的物理意义是:我走到ith 元素,能够达到的cursum的情况下,能否最后走到target,因为dfs从0,0开始,一直走到num.length 和target sum之后,return base case,然后回来,所以cache只是记录中间结果,所以代表能够reach target, true or false;
加cache提速:这里比较巧妙的是用Boolean ojbect数组来记录,如果!= null,return结果;
class Solution {
public boolean canPartition(int[] nums) {
if(nums == null || nums.length == 0) {
return false;
}
int sum = 0; int maxnum = 0;
for(int num : nums) {
sum += num;
maxnum = Math.max(maxnum, num);
}
if(sum % 2 != 0 || maxnum > sum / 2) {
return false;
}
Boolean[][] dp = new Boolean[nums.length][sum / 2 + 1];
boolean[] visited = new boolean[nums.length];
return dfs(nums, visited, sum / 2, 0, 0, dp);
}
private boolean dfs(int[] nums, boolean[] visited, int target, int cursum, int index,
Boolean[][] dp) {
if(cursum == target) {
return true;
}
if(index == nums.length || cursum > target) {
return false;
}
if(dp[index][cursum] != null) {
return dp[index][cursum];
}
for(int i = index; i < nums.length; i++) {
if(visited[i]) {
continue;
}
if(cursum + nums[i] <= target) {
visited[i] = true;
if(dfs(nums, visited, target, cursum + nums[i], i + 1, dp)) {
dp[i][cursum] = true;
return true;
}
visited[i] = false;
}
}
dp[index][cursum] = false;
return dp[index][cursum];
}
}