Leetcode 416. Partition Equal Subset Sum
416. Partition Equal Subset Sum
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.
动态规划,0/1背包问题。对于输入的数组nums,首先nums中各个元素之和要是偶数,然后就是找到可以将nums中的元素划分为2个不相交子集,并且这2个子集互补。
解法一:nums中的元素可以划分为2类:考虑了的和没考虑了的。由大值遍历到小值,具体可以根据代码画图理解。
1 public class Solution { 2 public boolean canPartition(int[] nums) { 3 if (nums == null || nums.length == 0) { 4 return false; 5 } 6 int sum = 0; 7 for (int num : nums) sum += num; 8 if (sum % 2 == 1) return false; 9 sum /= 2; 10 boolean[] dp = new boolean[sum + 1];//当前可以由考虑了的元素构成的值(每个元素最多出现1次) 11 //0可以由给定的nuns数组的元素组成给出 12 dp[0] = true; 13 int curSum = 0; 14 //nums中的元素可以划分为2类:考虑了的和没考虑了的 15 for (int i = 0; i < nums.length; i++) {//一个一个元素按顺序加入考虑了的划分中,从而考虑全部可以构成的数的值 16 int tmax = Math.min(curSum + nums[i], sum);//内循环的上限的有效值=min(当前考虑了的划分中的元素可以构成的最大的值,sum) 17 for (int j = tmax; j >= nums[i]; j--) { 18 //构成j值只有2种情况:包含nums[i],不包含nums[i] 19 //包含nums[i]:dp[j] = dp[j - nums[i]] 20 //不包含nums[i]:dp[j] = dp[j] 21 dp[j] = dp[j] || dp[j - nums[i]]; 22 } 23 if (dp[sum]) return true;//一旦满足直接返回,减少遍历 24 curSum += nums[i]; 25 } 26 return dp[sum]; 27 } 28 }
解法二:
1 public class Solution { 2 public boolean canPartition(int[] nums) { 3 int sum = 0; 4 for (int num : nums) sum += num; 5 if ((sum & 1) == 1) return false;//奇数还是偶数的判断 6 sum /= 2; 7 int n = nums.length; 8 boolean[][] dp = new boolean[n + 1][sum + 1];//dp[i][j]=true表示的能够用前i个数的子集构成j值 9 dp[0][0] = true;//用0个数构成0是true 10 for (int i = 1; i <= n; i++) dp[i][0] = true;//用i个数的子集可以构成0 11 for (int i = 1; i <= sum; i++) dp[0][i] = false;//用0个数不能构成大于0的任何数 12 for (int i = 1; i <= n ; i++) { 13 for (int j = 1; j <= sum; j++) { 14 //dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i - 1]] 15 //也是2种情况: 16 //包含nums[i - 1]:dp[i][j] = dp[i - 1][j] 17 //不包含nums[i - 1]:dp[i][j] = dp[i - 1][j - nums[i - 1]] 18 dp[i][j] = dp[i - 1][j]; 19 if (j >= nums[i - 1]) dp[i][j] = dp[i][j] || dp[i - 1][j - nums[i - 1]]; 20 } 21 } 22 return dp[n][sum]; 23 } 24 }