LeetCode 热题 HOT — 目标和

133 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 22 天,点击查看活动详情

目标和

原题地址

给你一个整数数组 nums 和一个整数 target

向数组中的每个整数前添加 '+''-' ,然后串联起所有整数,可以构造一个 表达式

例如,nums = [2, 1],可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1" 。 返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

示例 1:

输入:nums = [1,1,1,1,1], target = 3
输出:5
解释:一共有 5 种方法让最终目标和为 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

示例 2:

输入:nums = [1], target = 1
输出:1

提示:

  • 1 <= nums.length <= 20
  • 0 <= nums[i] <= 1000
  • 0 <= sum(nums[i]) <= 1000
  • -1000 <= target <= 1000

思路分析

方法一

  1. 分析题目,因为数组中的每个元素都可以加和减,因此每个元素有2种计算方式,那对于数组 nums 来说,总体的计算方式即为 2nums.length2^{nums.length}
  2. 需要将上述的所有计算方式遍历,比较计算的结果和给定的 target 值相同,则满足条件的计算方式就多一种;
  3. 因此定义一个辅助方法 help 遍历所有的计算方式,在遍历过程中维护一个结果值 res,若等于 target,则 res+=1
  4. 最后返回 res 即可。

方法二

  1. 定义一个数组 resres[i] 表示当 nums 长度为 i 时,所有运算结果为 target 的组合;
  2. res[0] = [0],当 nums 长度为0时,那得到的组合为 [0]
  3. 遍历 res,分别计算相加和相减时的值,得到最终的 res,最后返回为 target 的组合的数量即可;
  4. 本质上也是暴力解法,因此消耗的时间以及内存还是比较大的。

AC 代码

方法一

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var findTargetSumWays = function(nums, target) {
    let res = 0
    
    const help = (nums, target, index, sum) => {
        if (index === nums.length) {
            if (sum === target) {
                res++
            }
        } else {
            help(nums, target, index + 1, sum + nums[index])
            help(nums, target, index + 1, sum - nums[index])
        }
    }
    
    help(nums, target, 0, 0)
    return res
};

结果:

  • 执行结果: 通过
  • 执行用时:1944 ms, 在所有 JavaScript 提交中击败了28.43%的用户
  • 内存消耗:41 MB, 在所有 JavaScript 提交中击败了84.57%的用户
  • 通过测试用例:139 / 139

方法二

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var findTargetSumWays = function(nums, target) {
    const res = new Array(nums.length + 1).fill(null).map(item => new Array())

    res[0] = [0]

    for(let i = 1; i < res.length; i++) {
        for(let j = 0; j < res[i-1].length; j++){
            const plus = res[i-1][j] + nums[i-1] 
            const minus = res[i-1][j] - nums[i-1] 
            res[i].push(plus, minus)
        }
    }

    return res[nums.length].filter(num => num === target).length
};

结果:

  • 执行结果: 通过
  • 执行用时:3220 ms, 在所有 JavaScript 提交中击败了5.02%的用户
  • 内存消耗:109.4 MB, 在所有 JavaScript 提交中击败了5.01%的用户
  • 通过测试用例:139 / 139

END