方法——DFS:
代码1
dfs dfs(cur+1, res + nums[cur]),将cur,res都作为函数的参数传递,那么在回溯的时候不需要还原这些值
func findTargetSumWays(nums []int, target int) (ans int) {
var dfs func(int, int)
n := len(nums)
dfs = func(cur int, res int) {
if cur == n && res == target {
ans++
return
}
if cur == n {
return
}
dfs(cur+1, res + nums[cur])
dfs(cur+1, res - nums[cur])
}
dfs(0, 0)
return
}
方法二——动态规划:
dp切片的的i和j我们都多开了一个长度,原因是dp[i][j]中 i==0 我们用来表示一个啥也没有的情况,j == 0, 用来表示和为0的情况
代码2
func findTargetSumWays(nums []int, target int) int {
sum := 0
for _,v := range nums {
sum += v
}
a := sum - target
if a < 0 || a % 2 == 1 {
return 0
}
a = a >> 1
n := len(nums)
dp := make([][]int, n+1)
for i := range dp {
dp[i] = make([]int, a+1)
}
dp[0][0] = 1
for i := 1; i <= n; i++ {
v := nums[i-1]
for j := 0; j <= a; j++ {
if v > j {
dp[i][j] = dp[i-1][j]
}else {
dp[i][j] = dp[i-1][j] + dp[i-1][j-v]
}
}
}
return dp[n][a]
}
代码3
因为dp状态传递仅于上一层的dp有关所以我们只需要使用一层dp就可以,所以dp二维数组可以简化为一维数组,但如果在传递的时候不想使用临时变量,那么第二层for循环的 j 一定要到这来,以免用到的dp元素不是上一层的,而是这一层最新更新的
func findTargetSumWays(nums []int, target int) int {
sum := 0
for _, v := range nums {
sum += v
}
diff := sum - target
if diff < 0 || diff%2 == 1 {
return 0
}
neg := diff / 2
dp := make([]int, neg+1)
dp[0] = 1
for _, num := range nums {
for j := neg; j >= num; j-- {
dp[j] += dp[j-num]
}
}
return dp[neg]
}