Problem: 416. 分割等和子集
时间复杂度: O ( n m ) O(nm) O(nm): m m m为数组元素和的一半
空间复杂度: O ( n m ) O(nm) O(nm)
class Solution {
public boolean canPartition(int[] nums)
{
int n = nums.length;
int sum = 0;
for (int x : nums)
sum += x;
if (sum % 2 == 1)
return false;
int m = sum / 2;
// 注意:元素只可选一次
boolean[][] f = new boolean[n][m + 1];// 表示从前 i 个元素中选,使得这些数恰好 = j 的方案是否可行
if (nums[0] <= m)
f[0][nums[0]] = true;
for (int i = 1; i < n; i++)// 先枚举每个数
{
for (int j = 0; j <= m; j++)// 再枚举背包容量
{
f[i][j] = f[i - 1][j];// 不选当前数
if (nums[i] <= j)
// 不选当前数 选当前数
f[i][j] = f[i - 1][j] || f[i - 1][j - nums[i]];
}
if (f[i][m])// 只要出现一次f[i][m] 为真,即返回 true
return true;
}
return false;
// return f[n - 1][m];//走到这里必返回false
}
}
时间复杂度: O ( n m ) O(nm) O(nm): m m m为数组元素和的一半
空间复杂度: O ( m ) O(m) O(m)
class Solution {
public boolean canPartition(int[] nums)
{
int n = nums.length;
int sum = 0;
for (int x : nums)
sum += x;
if (sum % 2 == 1)
return false;
int m = sum / 2;
// 注意:元素只可选一次
boolean[] f = new boolean[m + 1];// 表示从前 i 个元素中选,使得这些数恰好 = j 的方案是否可行
if (nums[0] <= m)
f[nums[0]] = true;
for (int i = 1; i < n; i++)// 先枚举每个数
{
for (int j = m; j >= nums[i]; j--)// 再枚举背包容量
{
// 不选当前数 选当前数
f[j] = f[j] || f[j - nums[i]];
}
if (f[m])// 只要出现一次f[i][m] 为真,即返回 true
return true;
}
return false;
}
}