給定乙個非負整數陣列,a1, a2, …, an, 和乙個目標數,s。現在你有兩個符號 + 和 -。對於陣列中的任意乙個整數,你都可以從 + 或 -中選擇乙個符號新增在前面。
返回可以使最終陣列和為目標數 s 的所有新增符號的方法數。
本題是典型的「動態規劃」問題。設陣列的長度為n,
當陣列的前n-1項(nums[0]到nums[n-2])按照題中的要求得出了s-nums[n-1],則最後「+nums[n-1]」就滿足了題中要求,方法數加1。
或者陣列的前n-1項(nums[0]到nums[n-2])按照題中的要求得出了s+nums[n-1],則最後「-nums[n-1]」也滿足了題中要求,方法數加1。
設dp()
與findtargetsumways()
的意義相同,vectortemp
為當前vectornums
除最後一項外剩下的元素組成的陣列、len
為nums
的長度。
所以可以得出「狀態轉移公式」:dp(
nums
,s)=
dp(t
emp,
s−nu
ms[l
en−1
])+d
p(te
mp,s
+num
s[le
n−1]
)dp(nums,s) = dp(temp,s-nums[len-1])+dp(temp, s+nums[len-1])
dp(num
s,s)
=dp(
temp
,s−n
ums[
len−
1])+
dp(t
emp,
s+nu
ms[l
en−1
])普通的動態規劃遞迴函式會超時,在這裡不再說明。接下來用題中的「示例1」來說明使用「二維陣列」來解題的方法。
**中橫座標表示從前到後掃瞄陣列,當前掃瞄到的陣列元素。縱座標表示的是此時的目標數。對應的**內容則是對應的方法數。
如**中的(nums[2] = 1,-1)= 3表示的是掃瞄到陣列的第三個元素時,組合得到目標數s = -3的方法有3種。
從**種能夠得到(nums[4] = 1,3)= 5!
並且**中-s和s對應的方法數是相同的,這樣可以進一步縮短「二維陣列」的規模。
構造陣列:
初始化二維陣列的所有元素都為「0」。把第一行中與陣列第乙個元素相等的列數對應的**置為「1」。(這裡要注意的是,原本也要標記-s的情況,由於上述的原因而省略了,但如果s = 0,則-s = s,對應的位置就要標記兩次)
接下來從第一行開始迴圈,掃瞄每乙個元素,掃瞄到(i,
j)(i,j)
(i,j
)是非零元素時,其(i+
1,j±
nums
[i+1
]的絕對
值)(i+1,j\pm nums[i+1]的絕對值)
(i+1,j
±num
s[i+
1]的絕
對值)要加上(i,
j)(i,j)
(i,j
)對應的值。(掃瞄每一行之後別忘了把s=0對應的**元素本身×
最後一行,s的絕對值列對應的**元素就是本題要求的方法數
class
solution
int dp[20]
[1001];
int len = nums.
size()
;// 初始化dp陣列
memset
(dp,0,
sizeof
(dp));
dp[0]
[nums[0]
]=1;
dp[0]
[0]*
=2;for
(int i =
0; i < len -
1; i++
) dp[i +1]
[j + nums[i +1]
]+= dp[i]
[j];}}
// 每一行之後別忘了把s=0對應的**元素本身*2
dp[i +1]
[0]*
=2;}
return dp[len -1]
[abs
(s)];}
};
發現問題歡迎指出和糾正,謝謝! leetcode 494目標和 揹包dp
class solution def findtargetsumways self,nums,s int dp i j means solutionnums n len nums sum max sum nums sum min sum max dp dp 0for in range s 1 for...
0 1揹包 LeetCode 494 目標和
494.目標和 給定乙個非負整數陣列,a1,a2,an,和乙個目標數,s。現在你有兩個符號 和 對於陣列中的任意乙個整數,你都可以從 或 中選擇乙個符號新增在前面。返回可以使最終陣列和為目標數 s 的所有新增符號的方法數。示例 1 輸入 nums 1,1,1,1,1 s 3 輸出 5 解釋 1 1 ...
494 目標和 力扣
題意理解 給定一陣列,在每個數前增加 符號構成表示式,求和等於s的數量。問題分析 動規狀態量是前i個數字,和等於j的數量。狀態轉移方程是前i個數字,和等於j的數量等於前i 1個數字,和等於j 當前數字的數量 前i 1個數字,和等於j 當前數字的數量。其他鏈結 int findtargetsumway...