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: 1. Each of the array element will not exceed 100. 2. 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. https://leetcode.com/problems/partition-equal-subset-sum/discuss/90592/01-knapsack-detailed-explanation Nice solution. I just figured out the differences between this problem and 518. Coin Change 2. In this problem, we CANNOT reuse an element while it can be reused in LT518. That is why we have dp[i-1][j-nums[i-1]] in this problem and dp[i][j-coins[i-1]] in LT518 You don't need Arrays.fill(dp, false); Default elements in boolean array are initialized as false. class Solution { public boolean canPartition(int[] nums) { int sum = 0; for(int num : nums) sum += num; if(sum % 2 == 1) return false; sum = sum / 2; int n = nums.length; boolean[][] dp = new boolean[n + 1][sum + 1]; for(int i = 0; i < dp.length; i++){ Arrays.fill(dp[i], false); } dp[0][0] = true; for(int i = 1; i < n + 1; i++){ dp[i][0] = true; } for(int j = 1; j < sum + 1; j++){ dp[0][j] = false; } for(int i = 1; i < n + 1; i++){ for(int j = 1; j < sum + 1; j++){ dp[i][j] = dp[i - 1][j]; if(j >= nums[i - 1]){ dp[i][j] = dp[i][j] || dp[i - 1][j - nums[i - 1]]; } } } return dp[n][sum]; } } Subset Sum Problem Dynamic programming https://www.youtube.com/watch?v=K20Tx8cdwYY https://www.youtube.com/watch?v=r6I-ikllNDM But can we optimize it? It seems that we cannot optimize it in time. But we can optimize in space. We currently use two dimensional array to solve it, but we can only use one dimensional array. So the code becomes: public boolean canPartition(int[] nums) { int sum = 0; for (int num : nums) { sum += num; } if ((sum & 1) == 1) { return false; } sum /= 2; int n = nums.length; boolean[] dp = new boolean[sum+1]; Arrays.fill(dp, false); dp[0] = true; for (int num : nums) { for (int i = sum; i > 0; i--) { if (i >= num) { dp[i] = dp[i] || dp[i-num]; } } } return dp[sum]; } For number 5, dp[11] = dp[11] (not including the current 5, the 11 in the above row in the 2d array)or dp[11 -5] (, including the current 5 the 6 in the above row in the 2d array ) scan from back to front because you will use the former value which stores in the same array. If you scan from front to back, a few steps later, you will use current value but not the former value. Because dp[i] = dp[i] || dp[i-num] uses smaller index value dp[i-num]. When the current iteration begins, the values in dp[] are the result of previous iteration. Current iteration's result should only depend on the values of previous iteration. If you iterate from i = 0, then dp[i-num] will be overwritten before you use it, which is wrong. You can avoid this problem by iterating from i=sum
posted on 2018-11-06 07:53 猪猪🐷 阅读(119) 评论(0) 收藏 举报
浙公网安备 33010602011771号