給定乙個非負整數陣列,a1, a2, …, an, 和乙個目標數,s。現在你有兩個符號 + 和 -。對於陣列中的任意乙個整數,你都可以從 + 或 -中選擇乙個符號新增在前面。
返回可以使最終陣列和為目標數 s 的所有新增符號的方法數。
示例 1:
輸入: nums: [1, 1, 1, 1, 1], s: 3
輸出: 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
一共有5種方法讓最終目標和為3。
注意:
陣列非空,且長度不會超過20。
初始的陣列的和不會超過1000。
保證返回的最終結果能被32位整數存下。
動態規劃四步走:
問題拆解:
問題拆解就是要縮小問題規模。假設 nums: [1, 1, 1, 1, 1],s: 3。要找到目標和 3,對於陣列的最後乙個數字我們有兩種選擇:加上最後乙個數,這就要求前面的 n - 1 個數字的目標和為 2;減去最後乙個數,這就要求前面的 n - 1 個數字的目標和為 4。找到第 n 個問題與第 n - 1 個子問題的聯絡。
定義狀態:
我們定義 dp[i][j] 表示 「前 i 個數字組成目標和 j 的新增符號的方法數」。
推導狀態轉移方程:
由問題拆解,對於第 i 個數字 nums[i],有 + 和 - 兩種選擇,狀態轉移方程為:
dp[i][j] = dp[i - 1][j - nums[i]] + dp[i - 1][j + nums[i]]
寫成遞推的形式:
dp[i][j + nums[i]] += dp[i - 1][j]
dp[i][j - nums[i]] += dp[i - 1][j]
題目規定陣列的和不超過 1000,那麼 j 的最小值可能達到 -1000,所以我們給 dp[i][j] 的第二維預先增加 1000,防止出現負下標的情況,即
dp[i][j + nums[i] + 1000] += dp[i - 1][j + 1000]
dp[i][j - nums[i] + 1000] += dp[i - 1][j + 1000]
尋找邊界條件:class
solution
for(
int i =
1; i < nums.length; i++)}
}return s >
1000?0
: dp[nums.length -1]
[s +
1000];
}}
開始刷題LeetCode
今天決定開始刷題,每天至少一題,如果題目確實沒有解決出來沒有關係,但是要保證每天至少接觸了一道新的題目!一定要堅持下去,現在是個菜鳥可能會感覺有點難度,堅持下去,總有一天會好的!今天是第一天,做的第乙個題目 reverse words in a string given an input strin...
leetcode刷題歷程
難度 簡單 題目 給定乙個整數陣列 nums 和乙個目標值 target,請你在該陣列中找出和為目標值的那 兩個 整數,並返回他們的陣列下標。你可以假設每種輸入只會對應乙個答案。但是,你不能重複利用這個陣列中同樣的元素。示例 給定 nums 2,7,11,15 target 9 因為 nums 0 ...
LeetCode刷題總結
123 4567 891011 12 元素交換 swap a 1 a 3 sort排序 sort a.begin a.end 陣列顛倒 reverse a.begin a.end 陣列元素置為0 memset a,0,a.size 陣列取值 a.push back 定義二維陣列 vector vec...