LeetCode416 分割等和子集

2021-08-23 12:37:37 字數 1841 閱讀 4292

主要的思想**於0/1揹包問題,解決方法是動態規劃。我們可以想到,把陣列分割成兩份,並且和相等,那麼每乙份的和是總和的一半。那麼問題就可以轉化為找到一組數,使得他們的和逼近sum/2,最後判斷最大的和是否等於sum/2,如果是則說明存在這樣的組合,也就是存在子集。其和為sum/2,當然了另乙個集合的和也就是sum/2。注意到如果陣列的總和為奇數,則可以直接判斷不存在這樣的子集。所以在正式程式開始前可以先判斷陣列總和是否是奇數。

0/1揹包問題的公式為

其中f(n,y)為總價值,wi為貨物重量,pi為單個價值的重量,y為貨車容量,我們的目標是在不超過貨車容量的前提下使得所裝的貨物總價值最高。

解決此類問題有兩種解決方法,一種是直接利用遞迴方程求解,但是會有重複計算,可以建立乙個二維陣列記錄數值,令其初始值為-1,還可以避免重複計算。另一中方法是迭代程式代替遞迴,避免了重複計算,速度相對較快,但是所受侷限就是權值必須為整數。本題我們分別選擇遞迴程式和迭代程式來做,直接利用上述公式,可得下面**

方法一:遞迴程式

class solution 

int sum=accumulate(nums.begin(),nums.end(),0);

if(sum%2)

int n=nums.size(),cap=sum/2;

int** carray=new int*[n];

for(int i=0;i& nums,int** carray)

if(i==nums.size()-1)

if(cap方法二 ,迭代程式 

class solution

int cap=sum/2;

int n=nums.size();

int f[n][cap+1];

int ymax=min(nums[n-1]-1,cap);

//初始化fn,y表示剩餘容量,總的容量為sum/2

for(int y=0;y<=ymax;y++)

for(int y=nums[n-1];y<=cap;y++)

for(int i=n-2;i>0;i--)

}//i=0,上面的迭代計算會這一步計算做準備

if(cap>=nums[0])

else

return f[0][cap]==cap; //是否裝滿貨車}};

方法三,迭代程式的簡化版,**如下,主要是把二維空間壓縮到一維

class solution 

int n= nums.size();

int cap=sum/2;

bool dp[cap+1];

//初始化

for (int i = 1; i <=cap; i++)

dp[0] = true;

for (int i = 0; i0; j--)

} }return dp[cap];}};

壓縮思想**於下面的**,dp[i][j]和dp[i-1][j]的關係是層的關係,後者是前者的上一層,所以外層由i控制就夠了,主要比較的j這一層的值。為了防止覆蓋,要從大的值開始,相當於之前左邊是i,右邊是i-1,現在變成左邊是i,右邊是i+1,這和之前的揹包一致。

for (int i = 1; i <= n; i++) 

else

} }

其中dp[i][j]表示從第乙個元素到第i個元素是否存在能組成和為j的子集,如果可以為true,否則為false。

綜合比較,簡化版程式**減少了,但是理解起來有點困難,而且「揹包意圖」不太明顯。第一版程式雖然複雜,但是理解起來容易,而且如果程式要求具體的陣列集合,則第一版在計算完f(i,y)後可以直接確定權值(0/1)。

leetcode 416 分割等和子集

方法一 用動態規劃 class solution return res half 方法二 利用遞迴,dfs 此方法較動態規劃要好很多 基本思想 舉例子說明最容易理解,例如 nums 1,5,4,3,7 第一步 對陣列進行排序,nums 1,3,4,5,7 求出其和的一半 half 10 對於陣列中元...

LeetCode416 分割等和子集

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

LeetCode 416 分割等和子集

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