494. Target Sum [JavaScript]

本文探讨了解决特定类型问题的两种方法:深度优先搜索(DFS)与动态规划(DP)。通过对比,展示了DP如何显著提高解决这类问题的效率,尤其是在处理大量数据时。文章详细解释了DP的状态定义、边界状态及状态转移方程,并提供了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、解题思路

  最简单的方法就是列举所有的方式,记录其中满足目标值的次数,也就是采用DFS(深度优先搜索)实现:

const findTargetSumWays = (nums, S) => {
  let ans = 0
  let max = nums.length - 1
  dfs(0, S)
  return ans
  function dfs (startIndex, S) {
    if (startIndex === max) {
      if (S - nums[startIndex] === 0) {
        ans++
      }
      if (S + nums[startIndex] === 0) {
        ans++
      }
      return
    }
    dfs(startIndex + 1, S - nums[startIndex])
    dfs(startIndex + 1, S + nums[startIndex])
  }
}

  显然每个元素有执行两种操作的可能,所以时间复杂度为O(2^n),随着n的增大,该算法执行的时间是非常可怕的。

  再仔细观察该问题:

  ±a1 ± a2 ± a3 ± a4 ± a5 ... ∈ [-sum, +sum]

  由上述表达式可以得出,给定任意数组所产生的和值应该介于-sum和+sum之间,那么就可以采用动态规划的方式统计各种和值出现的次数:

  定义状态:

  dp[i][j]表示前i个元素形成和值为j的次数。

  边界状态:

  dp[0][0] = 1

  那么它的状态转移方程则为:

  dp[i][j] = dp[i - 1][j - nums[i - 1]] + dp[i - 1][j + nums[i - 1]]

  可能你已经发现j可能为负值,而对于数组来说是不存在负数下标的,所以这里需要对于数组的下标进行偏移。

  那么该问题的时间复杂度则降低为O(n * 2 * sum),具体代码如下:

二、代码实现

const findTargetSumWays = (nums, S) => {
  const max = nums.length

  const sum = nums.reduce((x, y) => x + y)

  // 特殊情况
  if (S > sum) {
    return 0
  }

  const dp = []
  dp[0] = new Array(sum * 2 + 1).fill(0) // 纯属为了打印出来好看^_^
  dp[0][sum] = 1

  for (let i = 1; i <= max; i++) {
    dp[i] = []
    for (let j = -sum; j <= sum; j++) {
      dp[i][j + sum] = (dp[i - 1][j - nums[i - 1] + sum] || 0) + (dp[i - 1][j + nums[i - 1] + sum] || 0)
    }
  }
  return dp[max][S + sum]
}

  如果本文对您有帮助,欢迎关注微信公众号,为您推送更多大前端相关的内容, 欢迎留言讨论,ε=ε=ε=┏(゜ロ゜;)┛。

  您还可以在这些地方找到我:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值