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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM