Welcome to Subscribe On Youtube
494. Target Sum
Description
You are given an integer array nums and an integer target.
You want to build an expression out of nums by adding one of the symbols '+' and '-' before each integer in nums and then concatenate all the integers.
- For example, if
nums = [2, 1], you can add a'+'before2and a'-'before1and concatenate them to build the expression"+2-1".
Return the number of different expressions that you can build, which evaluates to target.
Example 1:
Input: nums = [1,1,1,1,1], target = 3 Output: 5 Explanation: There are 5 ways to assign symbols to make the sum of nums be target 3. -1 + 1 + 1 + 1 + 1 = 3 +1 - 1 + 1 + 1 + 1 = 3 +1 + 1 - 1 + 1 + 1 = 3 +1 + 1 + 1 - 1 + 1 = 3 +1 + 1 + 1 + 1 - 1 = 3
Example 2:
Input: nums = [1], target = 1 Output: 1
Constraints:
1 <= nums.length <= 200 <= nums[i] <= 10000 <= sum(nums[i]) <= 1000-1000 <= target <= 1000
Solutions
Solution 1
Dynamic programming.
It is similar to the 0-1 Knapsack problem, except that the index may appear negative, which requires special handling.
Solution 2: Dynamic Programming (Space Optimization)
We can observe that in the state transition equation of Solution 1, the value of $f[i][j]$ is only related to $f[i - 1][j]$ and $f[i - 1][j - \textit{nums}[i - 1]]$. Therefore, we can eliminate the first dimension of the space and use only a one-dimensional array.
The time complexity is $O(m \times n)$, and the space complexity is $O(n)$.
-
class Solution { public int findTargetSumWays(int[] nums, int target) { int s = 0; for (int v : nums) { s += v; } if (s < target || (s - target) % 2 != 0) { return 0; } int n = (s - target) / 2; int[] dp = new int[n + 1]; dp[0] = 1; for (int v : nums) { for (int j = n; j >= v; --j) { dp[j] += dp[j - v]; } } return dp[n]; } } // Solution 2 class Solution { public int findTargetSumWays(int[] nums, int target) { int s = Arrays.stream(nums).sum(); if (s < target || (s - target) % 2 != 0) { return 0; } int n = (s - target) / 2; int[] f = new int[n + 1]; f[0] = 1; for (int num : nums) { for (int j = n; j >= num; --j) { f[j] += f[j - num]; } } return f[n]; } } -
class Solution { public: int findTargetSumWays(vector<int>& nums, int target) { int s = accumulate(nums.begin(), nums.end(), 0); if (s < target || (s - target) % 2 != 0) return 0; int n = (s - target) / 2; vector<int> dp(n + 1); dp[0] = 1; for (int& v : nums) for (int j = n; j >= v; --j) dp[j] += dp[j - v]; return dp[n]; } }; // Solution 2 class Solution { public: int findTargetSumWays(vector<int>& nums, int target) { int s = accumulate(nums.begin(), nums.end(), 0); if (s < target || (s - target) % 2) { return 0; } int n = (s - target) / 2; int f[n + 1]; memset(f, 0, sizeof(f)); f[0] = 1; for (int x : nums) { for (int j = n; j >= x; --j) { f[j] += f[j - x]; } } return f[n]; } }; -
class Solution: def findTargetSumWays(self, nums: List[int], target: int) -> int: s = sum(nums) if s < target or (s - target) % 2 != 0: return 0 n = (s - target) // 2 dp = [0] * (n + 1) dp[0] = 1 for v in nums: for j in range(n, v - 1, -1): dp[j] += dp[j - v] return dp[-1] # Solution 2 class Solution: def findTargetSumWays(self, nums: List[int], target: int) -> int: s = sum(nums) if s < target or (s - target) % 2: return 0 n = (s - target) // 2 f = [0] * (n + 1) f[0] = 1 for x in nums: for j in range(n, x - 1, -1): f[j] += f[j - x] return f[n] -
func findTargetSumWays(nums []int, target int) int { s := 0 for _, v := range nums { s += v } if s < target || (s-target)%2 != 0 { return 0 } n := (s - target) / 2 dp := make([]int, n+1) dp[0] = 1 for _, v := range nums { for j := n; j >= v; j-- { dp[j] += dp[j-v] } } return dp[n] } // Solution 2 func findTargetSumWays(nums []int, target int) int { s := 0 for _, x := range nums { s += x } if s < target || (s-target)%2 != 0 { return 0 } n := (s - target) / 2 f := make([]int, n+1) f[0] = 1 for _, x := range nums { for j := n; j >= x; j-- { f[j] += f[j-x] } } return f[n] } -
/** * @param {number[]} nums * @param {number} target * @return {number} */ var findTargetSumWays = function (nums, target) { let s = 0; for (let v of nums) { s += v; } if (s < target || (s - target) % 2 != 0) { return 0; } const m = nums.length; const n = (s - target) / 2; let dp = new Array(n + 1).fill(0); dp[0] = 1; for (let i = 1; i <= m; ++i) { for (let j = n; j >= nums[i - 1]; --j) { dp[j] += dp[j - nums[i - 1]]; } } return dp[n]; }; // Solution 2 /** * @param {number[]} nums * @param {number} target * @return {number} */ var findTargetSumWays = function (nums, target) { const s = nums.reduce((a, b) => a + b, 0); if (s < target || (s - target) % 2) { return 0; } const n = (s - target) / 2; const f = Array(n + 1).fill(0); f[0] = 1; for (const x of nums) { for (let j = n; j >= x; j--) { f[j] += f[j - x]; } } return f[n]; }; -
impl Solution { #[allow(dead_code)] pub fn find_target_sum_ways(nums: Vec<i32>, target: i32) -> i32 { let mut sum = 0; for e in &nums { sum += *e; } // -x + (sum - x) = target <-> -2 * x + sum = target <-> 2 * x = sum - target if sum < target || (sum - target) % 2 != 0 { // There is no way to get any expression in this case return 0; } let n = nums.len(); let m = (sum - target) / 2; let mut dp: Vec<Vec<i32>> = vec![vec![0; m as usize + 1]; n + 1]; // Initialize the dp vector dp[0][0] = 1; // Begin the actual dp phase for i in 1..=n { for j in 0..=m as usize { // nums[i - 1] is not included dp[i][j] = dp[i - 1][j]; if nums[i - 1] <= (j as i32) { // nums[i - 1] is included dp[i][j] += dp[i - 1][j - (nums[i - 1] as usize)]; } } } dp[n][m as usize] } } // Solution 2 impl Solution { pub fn find_target_sum_ways(nums: Vec<i32>, target: i32) -> i32 { let s: i32 = nums.iter().sum(); if s < target || (s - target) % 2 != 0 { return 0; } let n = ((s - target) / 2) as usize; let mut f = vec![0; n + 1]; f[0] = 1; for x in nums { for j in (x as usize..=n).rev() { f[j] += f[j - x as usize]; } } f[n] } } -
function findTargetSumWays(nums: number[], target: number): number { const s = nums.reduce((a, b) => a + b, 0); if (s < target || (s - target) % 2) { return 0; } const [m, n] = [nums.length, ((s - target) / 2) | 0]; const f: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); f[0][0] = 1; for (let i = 1; i <= m; i++) { for (let j = 0; j <= n; j++) { f[i][j] = f[i - 1][j]; if (j >= nums[i - 1]) { f[i][j] += f[i - 1][j - nums[i - 1]]; } } } return f[m][n]; } // Solution 2 function findTargetSumWays(nums: number[], target: number): number { const s = nums.reduce((a, b) => a + b, 0); if (s < target || (s - target) % 2) { return 0; } const n = ((s - target) / 2) | 0; const f = Array(n + 1).fill(0); f[0] = 1; for (const x of nums) { for (let j = n; j >= x; j--) { f[j] += f[j - x]; } } return f[n]; }