有一堆石頭,用整數陣列stones
表示。其中stones[i]
表示第i
塊石頭的重量。
每一回合,從中選出任意兩塊石頭,然後將它們一起粉碎。假設石頭的重量分別為x
和y
,且x <= y
。那麼粉碎的可能結果如下:
最後,最多隻會剩下一塊石頭。返回此石頭最小的可能重量。如果沒有石頭剩下,就返回0
。
示例 1:
輸入:stones = [2,7,4,1,8,1]示例 2:輸出:1
解釋:組合 2 和 4,得到 2,所以陣列轉化為 [2,7,1,8,1],
組合 7 和 8,得到 1,所以陣列轉化為 [2,1,1,1],
組合 2 和 1,得到 1,所以陣列轉化為 [1,1,1],
組合 1 和 1,得到 0,所以陣列轉化為 [1],這就是最優值。
輸入:stones = [31,26,33,21,40]示例 3:輸出:5
輸入:stones = [1,2]最值問題一般都用動態規劃來解決。其實本題和416.分割等和子集輸出:1
很相似,也是可以採用01揹包來解決。
根據題意,本題其實就是把一堆石頭分成兩堆,求兩堆石頭重量差最小值。要想讓兩堆石頭的差值盡可能小,則兩堆石頭的總重量應盡可能地接近於所有石頭的總重量/2。
我們可以明確:物品就是石頭,物品的重量和價值就是每一塊石頭的重量,揹包的容量就是所有石頭的總重量/2。
動態規劃五部曲:
確定dp陣列以及其下標的含義
dp[j]
表示為容量為j
的揹包最多可以背的石頭重量
確定遞推公式
根據01揹包基礎
中對遞推公式的推導可知,本題的遞推公式為dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])
dp陣列的初始化
dp[j] = 0
確定遍歷順序
只能先遍歷物品,再遍歷揹包。 注意這種方式揹包的遍歷順序是不一樣的,要從大往小遍歷。
舉例推導dp陣列
以 stones = [2,4,1,1] 為例
1049 最後一塊石頭的重量 II
1049.最後一塊石頭的重量 ii 有一堆石頭,每塊石頭的重量都是正整數。每一回合,從中選出任意兩塊石頭,然後將它們一起粉碎。假設石頭的重量分別為 x 和 y,且 x y。那麼粉碎的可能結果如下 如果 x y,那麼兩塊石頭都會被完全粉碎 如果 x y,那麼重量為 x 的石頭將會完全粉碎,而重量為 y...
最後一塊石頭重量
有一堆石頭,每塊石頭的重量都是正整數。每一回合,從中選出兩塊 最重的 石頭,然後將它們一起粉碎。假設石頭的重量分別為 x 和 y,且 x y。那麼粉碎的可能結果如下 如果 x y,那麼兩塊石頭都會被完全粉碎 如果 x y,那麼重量為 x 的石頭將會完全粉碎,而重量為 y 的石頭新重量為 y x。最後...
C語言重構 1049 最後一塊石頭的重量 II
所有題目源 git位址 題目有一堆石頭,每塊石頭的重量都是正整數。每一回合,從中選出任意兩塊石頭,然後將它們一起粉碎。假設石頭的重量分別為 x 和 y,且 x y。那麼粉碎的可能結果如下 如果 x y,那麼兩塊石頭都會被完全粉碎 如果 x y,那麼重量為 x 的石頭將會完全粉碎,而重量為 y 的石頭...