416. Partition Equal Subset Sum
来源:互联网 发布:百度黑马程序员 编辑:程序博客网 时间:2024/05/21 06:57
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: trueExplanation: The array can be partitioned as [1, 5, 5] and [11].
Example 2:
Input: [1, 2, 3, 5]Output: falseExplanation: The array cannot be partitioned into equal sum subsets.这道题类似于背包问题,动规原则取决于当前包背还是不背。在top solution有个比较好的解释:
This problem is essentially let us to find whether there are several numbers in a set which are able to sum to a specific value (in this problem, the value is sum/2).
Actually, this is a 0/1 knapsack problem, for each number, we can pick it or not. Let us assume dp[i][j] means whether the specific sum j can be gotten from the first i numbers. If we can pick such a series of numbers from 0-i whose sum is j, dp[i][j] is true, otherwise it is false.
Base case: dp[0][0] is true; (zero number consists of sum 0 is true)
Transition function: For each number, if we don't pick it, dp[i][j] = dp[i-1][j], which means if the first i-1 elements has made it to j, dp[i][j] would also make it to j (we can just ignore nums[i]). If we pick nums[i]. dp[i][j] = dp[i-1][j-nums[i]], which represents that j is composed of the current value nums[i] and the remaining composed of other previous numbers. Thus, the transition function is dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i]]
talking is cheap:
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[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];}
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];}还有一种更快的方法,类似于二分法:
public class Solution { public boolean canPartition(int[] nums) { int sum = 0; for (int i = 0; i < nums.length; i++) { sum += nums[i]; } if (sum % 2 != 0) { return false; } for (int i = 0; i < nums.length; i++) { int tmp = nums[i]; if (tmp == sum / 2) { return true; } for (int j = i + 1; j < nums.length; j++) { tmp += nums[j]; if (tmp == sum / 2) { return true; } else if (tmp > sum / 2) { tmp = tmp - nums[j]; } } } return false; }}
- 416. Partition Equal Subset Sum
- 416. Partition Equal Subset Sum
- 416. Partition Equal Subset Sum
- 416. Partition Equal Subset Sum
- 416. Partition Equal Subset Sum
- 416. Partition Equal Subset Sum
- 416. Partition Equal Subset Sum
- 416. Partition Equal Subset Sum
- 416. Partition Equal Subset Sum
- 416. Partition Equal Subset Sum
- 416. Partition Equal Subset Sum
- 416. Partition Equal Subset Sum
- 416. Partition Equal Subset Sum
- 416. Partition Equal Subset Sum
- 416. Partition Equal Subset Sum
- 416. Partition Equal Subset Sum
- 416. Partition Equal Subset Sum
- 416. Partition Equal Subset Sum
- 10——字符个数统计
- IDEA的一些设置
- Spark性能优化 开发调优
- etcd v3命令和API
- 欢迎使用CSDN-markdown编辑器
- 416. Partition Equal Subset Sum
- PHP版 RabbitMQ小技巧(一)用代码获得服务器上的消息队列名
- Field 'id' doesn't have a default value
- 线程简介
- 精简Linux内核编译的简单方法
- CListCtrl的部分用法
- 常用工具推荐
- Servlet-3
- CountDownLatch使用之等待超时