分割等和子集 leetcode416

2021-10-10 11:25:04 字數 1846 閱讀 2141

給定乙個只包含正整數非空陣列。是否可以將這個陣列分割成兩個子集,使得兩個子集的元素和相等。

注意:

每個陣列中的元素不會超過 100

陣列的大小不會超過 200

示例 1:

輸入: [1, 5, 11, 5]

輸出: true

解釋: 陣列可以分割成 [1, 5, 5] 和 [11].

示例 2:

輸入: [1, 2, 3, 5]

輸出: false

解釋: 陣列不能分割成兩個元素和相等的子集.

思路:01揹包問題求解

1.引用:經典動態規劃:0-1揹包問題的變體

那麼對於這個問題,我們可以先對集合求和,得出sum,把問題轉化為揹包問題:

給乙個可裝載重量為sum/2的揹包和n個物品,每個物品的重量為nums[i]。現在讓你裝物品,是否存在一種裝法,能夠恰好將揹包裝滿?

第一步要明確兩點,「狀態」和「選擇」。

狀態就是「揹包的容量」和「可選擇的物品」,選擇就是「裝進揹包」或者「不裝進揹包」。

第二步要明確dp陣列的定義。

按照揹包問題的套路,可以給出如下定義:

dp[i][j] = x表示,對於前i個物品,當前揹包的容量為j時,若x為true,則說明可以恰好將揹包裝滿,若x為false,則說明不能恰好將揹包裝滿。

比如說,如果dp[4][9] = true,其含義為:對於容量為 9 的揹包,若只是用前 4 個物品,可以有一種方法把揹包恰好裝滿。

或者說對於本題,含義是對於給定的集合中,若只對前 4 個數字進行選擇,存在乙個子集的和可以恰好湊出 9。

根據這個定義,我們想求的最終答案就是dp[n][sum/2],base case 就是dp[..][0] = true和dp[0][..] = false,因為揹包沒有空間的時候,就相當於裝滿了,而當沒有物品可選擇的時候,肯定沒辦法裝滿揹包。

第三步,根據「選擇」,思考狀態轉移的邏輯。

回想剛才的dp陣列含義,可以根據「選擇」對dp[i][j]得到以下狀態轉移:

如果不把nums[i]算入子集,或者說你不把這第i個物品裝入揹包,那麼是否能夠恰好裝滿揹包,取決於上乙個狀態dp[i-1][j],繼承之前的結果。

如果把nums[i]算入子集,或者說你把這第i個物品裝入了揹包,那麼是否能夠恰好裝滿揹包,取決於狀態dp[i - 1][j-nums[i-1]]。

首先,由於i是從 1 開始的,而陣列索引是從 0 開始的,所以第i個物品的重量應該是nums[i-1],這一點不要搞混。

dp[i - 1][j-nums[i-1]]也很好理解:你如果裝了第i個物品,就要看揹包的剩餘重量j - nums[i-1]限制下是否能夠被恰好裝滿。

換句話說,如果j - nums[i-1]的重量可以被恰好裝滿,那麼只要把第i個物品裝進去,也可恰好裝滿j的重量;否則的話,重量j肯定是裝不滿的。

return true;//有就提前返回

}return dp[n][sum];}};

分割等和子集

給定乙個只包含正整數的非空陣列。是否可以將這個陣列分割成兩個子集,使得兩個子集的元素和相等。示例 1 輸入 1 5,11 5 輸出 true 解釋 陣列可以分割成 1,5,5 和 11 示例 2 輸入 1 2,3 5 輸出 false 解釋 陣列不能分割成兩個元素和相等的子集.思路 1.首先求陣列總...

分割等和子集

給定乙個只包含正整數的非空陣列。是否可以將這個陣列分割成兩個子集,使得兩個子集的元素和相等。注意 每個陣列中的元素不會超過 100 陣列的大小不會超過 200 示例 1 輸入 1,5,11,5 輸出 true 解釋 陣列可以分割成 1,5,5 和 11 示例 2 輸入 1,2,3,5 輸出 fals...

leetcode 分割等和子集(01揹包)

給定乙個只包含正整數的非空陣列。是否可以將這個陣列分割成兩個子集,使得兩個子集的元素和相等。注意 每個陣列中的元素不會超過 100 陣列的大小不會超過 200 示例 1 輸入 1,5,11,5 輸出 true 解釋 陣列可以分割成 1,5,5 和 11 示例 2 輸入 1,2,3,5 輸出 fals...