LeetCode 416 分割等和子集
LeetCode 416 分割等和子集
问题描述:
给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
注意:
每个数组中的元素不会超过 100
数组的大小不会超过 200
动态规划(0-1背包问题)
执行用时:21 ms, 在所有 Java 提交中击败了69.80%的用户
内存消耗:38.5 MB, 在所有 Java 提交中击败了58.03%的用户
class Solution {
public boolean canPartition(int[] nums) {
int n = nums.length;
//边界条件
if (n < 2) {
return false;
}
int sum = 0, maxNum = 0;
for (int num : nums) {
sum += num;
maxNum = Math.max(maxNum, num);
}
if (sum % 2 != 0) {
return false;
}
int target = sum / 2;
if (maxNum > target) {
return false;
}
//递归过程
//dp[i][j]表示数组中[0, i]范围是否能够选出和为j的子集
//若nums[i]<=j,则dp[i][j] = dp[i-1][j] || dp[i][j-nums[i]]
//若nums[i]>j,则dp[i][j] = dp[i-1][j]
//初始状态dp[i][0] = true、dp[i][nums[i]] = true
//由上可知dp[i][j]可能由dp[i-1][j]、dp[i-1][j-1]...dp[i-1][0]确定
//因此可简化dp数组为boolean[] dp = new boolean[target+1]
boolean[] dp = new boolean[target + 1];
dp[0] = true;
for (int i = 0; i < n; i++) {
int num = nums[i];
for (int j = target; j >= num; --j) {
dp[j] |= dp[j - num];
}
}
return dp[target];
}
}