* Brute Force - DFS
* Time O(2^N) | Space O(N)
* https://leetcode.com/problems/target-sum/
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
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;
};
* DP - Top Down
* Matrix - Memoization
* Time O(N * M) | Space O(N * M)
* https://leetcode.com/problems/target-sum/
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
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];
};
* DP - Bottom Up
* Matrix - Tabulation
* Time O(N * M) | Space O(N * M)
* https://leetcode.com/problems/target-sum/
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
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;
}
}
};
* DP - Top Down
* Array - Tabulation
* Time O(N * M) | Space O(M)
* https://leetcode.com/problems/target-sum/
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
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;
};