class Solution {
private int[] nums;
private int[][] cache;
public int findTargetSumWays(int[] nums, int target) {
for (int x : nums) target += x;
if (target < 0 || target % 2 == 1) return 0;
target /= 2;
this.nums = nums;
int n = nums.length;
cache = new int[n][target + 1];
for (int i = 0; i < n; i++)
Arrays.fill(cache[i], -1); // -1 表示没用访问过
return dfs(n - 1, target);
}
private int dfs(int i, int c) {
if (i < 0) return c == 0 ? 1 : 0;
if (cache[i][c] != -1) return cache[i][c];
if (c < nums[i]) return cache[i][c] = dfs(i - 1, c);
return cache[i][c] = dfs(i - 1, c) + dfs(i - 1, c - nums[i]);
}
}
二 · 1:1 翻译成递推
class Solution {
public int findTargetSumWays(int[] nums, int target) {
for (int x : nums) target += x;
if (target < 0 || target % 2 == 1) return 0;
target /= 2;
int n = nums.length;
int[][] f = new int[n + 1][target + 1];
f[0][0] = 1;
for (int i = 0; i < n; ++i)
for (int c = 0; c <= target; ++c)
if (c < nums[i]) f[i + 1][c] = f[i][c];
else f[i + 1][c] = f[i][c] + f[i][c - nums[i]];
return f[n][target];
}
}
三 · 空间优化:两个数组(滚动数组)
class Solution {
public int findTargetSumWays(int[] nums, int target) {
for (int x : nums) target += x;
if (target < 0 || target % 2 == 1) return 0;
target /= 2;
int n = nums.length;
int[][] f = new int[2][target + 1];
f[0][0] = 1;
for (int i = 0; i < n; ++i)
for (int c = 0; c <= target; ++c)
if (c < nums[i]) f[(i + 1) % 2][c] = f[i % 2][c];
else f[(i + 1) % 2][c] = f[i % 2][c] + f[i % 2][c - nums[i]];
return f[n % 2][target];
}
}
四 · 空间优化:一个数组
class Solution {
public int findTargetSumWays(int[] nums, int target) {
for (int x : nums) target += x;
if (target < 0 || target % 2 == 1) return 0;
target /= 2;
int[] f = new int[target + 1];
f[0] = 1;
for (int x : nums)
for (int c = target; c >= x; --c)
f[c] += f[c - x];
return f[target];
}
}