Leetcode 494 Target Sum 动态规划 背包+滚动数据

这是一道水题,作为没有货的水货楼主如是说。

题意:已知一个数组nums {a1,a2,a3,.....,an}(其中0<ai <=1000(1<=k<=n, n<=20))和一个数S

c1a1c2a2c3a3......cnan = S, 其中ci(1<=i<=n)可以在加号和减号之中任选。

求有多少种{c1,c2,c3,...,cn}的排列能使上述等式成立。

例如:

输入:nums is [1, 1, 1, 1, 1], S is 3.
输出 : 5
符合要求5种等式:

-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

但是看完题的你们说,楼主这个题目的难度是中等题呀!

好吧,楼主说错了,它是中等题,但毋庸置疑这是一道动态规划的水题,是一个背包问题,不知道的背包问题的同学请百度下《背包九讲》。

注意:看那个《背包九讲》可能开始会感到生涩难懂,但是前方高能东西都是牛逼的东西。

回归到本题中,乍一看它是一个搜索问题,即搜索出所有可能的解即可,因为n最多为20,搜索一把也能顺利完成,解决也是比较容易的。

但是就没有更好的方法了吗?这时我们注意到0<ai <=1000这个条件,这么小的数值让我们很快联想到了动态规划。

没错,这是一个多阶段的背包问题,其中的难点是负数这么表示。

我们可以将[-max,max]映射到[0,2*max]就解决问题了。

我们现在可以想出以下的状态转移方程:

dp[i][j] = dp[i-1][j-a[i]] + dp[i-1][j+a[i]](1 <= i <= n, 0< j < 2 * sum(a[i]) + 1)

即i代表有多少个数,j - sum(a[i])代表每一种算出来的答案,dp[i][j]代表在答案j - sum(a[i])的情况下的c1,c2,c3,...,ci}的排列牌数。很明显当前的状态dp[i][j]是从上一次(i-1)的数加上当前的 a[i]得到的。

这样我们只要开出一个n * (2 * sum(a[i]) + 1)的数组,在O(n * (2 * sum(a[i]) + 1))的时间复杂度下解决这个问题。

那么还可以优化吗?答案是肯定的。

我们从状态转移方程中不难看出,在每一次转移的时候都只用了i-1次的答案和i次的结果,为此我们可以使用滚动数据对它进行优化。

只要我们开出2 * (2 * sum(a[i]) + 1)的数据,这样我们又再次优化了内存。

即我们可以在时间复杂度为O(n * (2 * sum(a[i]) + 1)) 和空间复杂度(2 * (2 * sum(a[i]) + 1)) 的情况下解决该问题。

下面上golang的代码(居然没有golang的语言编辑器,求增加)

 1 func findTargetSumWays(nums []int, S int) int {
 2     mid := 0
 3     for _,v := range nums{
 4         mid += v
 5     }
 6     dp := make([][]int, 2)
 7     for i,_:=range dp{
 8         dp[i] = make([]int, mid + mid + 1)
 9     }
10     dp[0][mid] = 1
11     for i,v := range nums{
12         for j,_:= range dp[(i + 1)%2]{
13             dp[(i + 1)%2][j] = 0
14         }
15         for j:=0; j <= mid + mid; j++{
16             if j >= v {
17                 dp[(i+1)%2][j-v] += dp[i%2][j]
18             }
19             if j + v <= mid + mid {
20                 dp[(i+1)%2][j+v] += dp[i%2][j]
21             }
22         }
23     }
24     if S > mid || S < -mid{
25         return 0
26     }
27
28     return dp[len(nums)%2][S+mid]
29 }
时间: 2024-10-03 05:52:26

Leetcode 494 Target Sum 动态规划 背包+滚动数据的相关文章

[Leetcode] DP -- Target Sum

You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symbols + and -. For each integer, you should choose one from + and - as its new symbol. Find out how many ways to assign symbols to make sum of integers

494. Target Sum - Unsolved

https://leetcode.com/problems/target-sum/#/description You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symbols + and -. For each integer, you should choose one from + and - as its new symbol. Find out h

494. Target Sum

You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symbols + and -. For each integer, you should choose one from + and - as its new symbol. Find out how many ways to assign symbols to make sum of integers

494. Target Sum 添加标点符号求和

[抄题]: You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symbols + and -. For each integer, you should choose one from + and - as its new symbol. Find out how many ways to assign symbols to make sum of int

[LC] 494. Target Sum

You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symbols + and -. For each integer, you should choose one from + and - as its new symbol. Find out how many ways to assign symbols to make sum of integers

LeetCode Target Sum

原题链接在这里:https://leetcode.com/problems/target-sum/description/ 题目: You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symbols + and -. For each integer, you should choose one from + and - as its new symbol.

Leetcode 1191 K-Concatenation Maximum Sum 动态规划

Leetcode 1191 K-Concatenation Maximum Sum 动态规划 题目描述 Given an integer array arr and an integer k, modify the array by repeating it k times. For example, if arr = [1, 2] and k = 3 then the modified array will be [1, 2, 1, 2, 1, 2]. Return the maximum s

LeetCode --- 1. Two Sum

题目链接:Two Sum Given an array of integers, find two numbers such that they add up to a specific target number. The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Plea

算法-Partition Equal Subset Sum(动态规划)

一直以来,动态规划是我的问题,今天看到了一道动态规划的题,做了好久,也思考了好久,借鉴别人的代码才把这个问题理解到. 题意: Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal. 样例: Given nums = [