携手创作,共同成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第26天,点击查看活动详情
目标和
给你一个整数数组
nums
和一个整数target
。向数组中的每个整数前添加'+'
或'-'
,然后串联起所有整数,可以构造一个 表达式 :返回可以通过上述方法构造的、运算结果等于target
的不同 表达式 的数目。
分析
-
给定一个数组和一个target,数组中的数可以取正值或者负值,给出运算结果等于target的方法数。把target设置为包的容量,把数组比作物品,数字取正值或者负值比作物品的价值,每个数字只能使用一次,就很像01背包问题,但是与01背包问题不同的是需要把所有的物品都装到背包里,正好达到背包的容量。背包问题使用dp来解决,因此确定一下dp状态的定义和状态转移
-
状态定义: dp(i,sum)表示遍历到数组的第i个位置时,使得当前的和为sum的方法数
-
状态转移:
- 当取正值时,dp(i+1,sum) = dp(i,sum+nums[i])
- 当取负值时,dp(i+1, sum) = dp(i,sum-nums[i])
-
答案就是dp(nums.length-1,target),当和为target并且遍历完数组后得到的方法数
-
优化:记忆化动态规划,把之前算过的子问题存住,可以有效提升算法效率,一般记忆化的数据都会存在Map中,由于我们的dp状态定义,可以把key设置为状态中的两个参数
代码
var findTargetSumWays = function(nums, target) {
const map = new Map()
function dp(idx, sum) {
if(idx === nums.length) return sum === target ? 1 : 0
if(map.has(`${idx}-${sum}`)) return map.get(`${idx}-${sum}`)
const res = dp(idx+1, sum+nums[idx]) + dp(idx+1, sum-nums[idx])
map.set(`${idx}-${sum}`, res)
return res
}
return run(0, 0)
};
总结
- 今天依旧是01背包问题的变体,能通过题目描述分析到是背包问题可能还是有些难度,在确定了背包问题后,因为01背包问题是一类典型的dp问题,所以题解很快就能写出来,应该更多的时间放在审题上
- 今天也是有收获的一天