题目描述
给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
示例:
输入: [1, 5, 11, 5]
输出: true
解释: 数组可以分割成 [1, 5, 5] 和 [11].
总结
SC其实也是动态规划
Sample Code
class Solution {
public boolean canPartition(int[] nums) {
int sum = 0;
for (int num : nums) {
sum += num;
}
//若和为奇数,不存在分割等和子集
if (sum % 2 == 1) {
return false;
}
return partition(nums, nums.length - 1, sum >> 1);
}
private boolean partition(int[] nums, int i, int half_sum) {
//当已有子集之和超过元素之和的一半或放完数字无解返回
if (half_sum < 0 || i < 0)
return false;
//得到正确解答后返回
if (half_sum == 0)
return true;
//优化部分,当某个元素过大(超过所有元素和的一半)时返回
if(nums[i]>half_sum)
return false;
//选择索引为 i 的元素是否放入
return partition(nums, i - 1, half_sum - nums[i]) || partition(nums, i - 1, half_sum);
}
}
动态规划
public class Solution {
public boolean canPartition(int[] nums) {
int s = 0;
for (int num : nums) s += num;
if ((s & 1) == 1) return false;
int target = s / 2;
boolean[] dp = new boolean[target + 1];
for (int j = 1; j < target + 1; j++) {
if (nums[0] == j) {
dp[j] = true;
break;
}
}
for (int i = 1; i < nums.length; i++) {
// 后面的容量越来越小,因此没有必要再判断了,退出当前循环
for (int j = target; j >= nums[i]; j--)
dp[j] = dp[j] || dp[j - nums[i]];
if(dp[target] == true) return true;
}
return dp[target];
}
}
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/partition-equal-subset-sum