法1:dp
基础解法,必须掌握!!!
本质是『0-1背包』问题,背包问题大总结
Python
class Solution:
def canPartition(self, nums: List[int]) -> bool:
if sum(nums) % 2 == 1 or max(nums) > sum(nums)/2:
return False
target = sum(nums)//2
n = len(nums)
dp = [[False]*(target+1) for _ in range(n)] # dp[i][j]表示从[0, i]中能否凑出和为j
for i in range(n):
dp[i][nums[i]] = True
dp[i][0] = True
for i in range(1, n):
for j in range(1, target+1):
if j < nums[i]:
dp[i][j] = dp[i-1][j]
else:
dp[i][j] = dp[i-1][j] or dp[i-1][j-nums[i]]
return dp[n-1][target]
Java
class Solution {
public boolean canPartition(int[] nums) {
if (nums.length < 2) {
return false;
}
int sum = 0, maxVal = 0;
for (int i : nums) {
sum += i;
maxVal = i > maxVal ? i : maxVal;
}
if (sum % 2 == 1 || maxVal > sum / 2) {
return false;
}
int n = nums.length, target = sum / 2;
boolean[][] dp = new boolean[n][target + 1]; // dp[i][j]表示能否从[0, i]组合sum为j
for (int i = 0; i < nums.length; ++i) {
dp[i][nums[i]] = true;
dp[i][0] = true;
}
for (int i = 1; i < nums.length; ++i) {
for (int j = 1; j <= target; ++j) {
if (j < nums[i]) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i]]; // 取nums[i] or not
}
}
}
return dp[n - 1][target];
}
}