var findTargetSumWays = (nums, target, index = 0, sum = 0) => {
const isBaseCase = (index === nums.length);
if (isBaseCase) {
const isTarget = (sum === target);
if (isTarget) return 1;
return 0;
}
return dfs(nums, target, index, sum);
}
var dfs = (nums, target, index, sum) => {
const left = findTargetSumWays(nums, target, (index + 1), (sum + nums[index]));
const right = findTargetSumWays(nums, target, (index + 1), (sum - nums[index]));
return (left + right);
}
var findTargetSumWays = (nums, target) => {
const total = nums.reduce((sum, num) => (sum + num), 0);
return calculate(nums, target, total);
}
var initMemo = (nums, total) => new Array(nums.length).fill()
.map(() => new Array(((total + 1) << 1)).fill(null));
const calculate = (nums, target, total, index = 0, sum = 0, memo = initMemo(nums, total)) => {
const isBaseCase = (index === nums.length);
if (isBaseCase) {
const isTarget = (sum === target);
if (isTarget) return 1;
return 0;
}
const hasSeen = (memo[index][(sum + total)] != null);
if (hasSeen) return memo[index][(sum + total)];
return dfs(nums, target, total, index, sum, memo);
}
var dfs = (nums, target, total, index, sum, memo) => {
const left = calculate(nums, target, total, (index + 1), (sum + nums[index]), memo);
const right = calculate(nums, target, total, (index + 1), (sum - nums[index]), memo);
memo[index][(sum + total)] = (left + right);
return memo[index][(sum + total)];
}
var findTargetSumWays = (nums, target) => {
const total = nums.reduce((sum, num) => (sum + num), 0);
const tabu = initTabu(nums, total);
search(nums, total, tabu);
return (Math.abs(target) <= total)
? tabu[(nums.length - 1)][(target + total)]
: 0;
};
var initTabu = (nums, total) => {
const tabu = new Array(nums.length).fill()
.map(() => new Array(((total + 1) << 1)).fill(0));
const [ left, right ] = [ (total + nums[0]), (total - nums[0]) ];
tabu[0][left] = 1;
tabu[0][right] += 1;
return tabu;
}
var search = (nums, total, tabu) => {
for (let i = 1; (i < nums.length); i++) {
for (let sum = (-total); (sum <= total); sum++) {
const isInvalid = (tabu[(i - 1)][(sum + total)] <= 0);
if (isInvalid) continue;
const dpSum = tabu[(i - 1)][sum + total];
const left = ((sum + nums[i]) + total);
const right = ((sum - nums[i]) + total);
tabu[i][left] += dpSum;
tabu[i][right] += dpSum;
}
}
}
var findTargetSumWays = (nums, target) => {
const total = nums.reduce((sum, num) => (sum + num), 0);
let tabu = getTabu(nums, total);
tabu = search(nums, total, tabu);
return (Math.abs(target) <= total)
? tabu[(target + total)]
: 0
}
var initTabu = (total) => new Array((total + 1) << 1).fill(0);
var getTabu = (nums, total) => {
const tabu = initTabu(total);
const [ left, right ] = [ (total + nums[0]), (total - nums[0]) ];
tabu[left] = 1;
tabu[right] += 1;
return tabu;
}
var search = (nums, total, tabu) => {
for (let i = 1; (i < nums.length); i++) {
const num = nums[i];
const temp = initTabu(total);
tabu = update(num, total, tabu, temp);
}
return tabu;
}
var update = (num, total, tabu, temp) => {
for (let sum = (-total); (sum <= total); sum++) {
const isInvalid = (tabu[sum + total] <= 0);
if (isInvalid) continue;
const dpSum = tabu[sum + total];
const left = ((sum + num) + total);
const right = ((sum - num) + total);
temp[left] += dpSum;
temp[right] += dpSum;
}
return temp;
}