LeetCode 分割整數陣列,分割為兩部分的和相等
阿新 • • 發佈:2019-01-08
/*! * @file 陣列分割.cpp * @Date: 2018/03/22 15:03 * @author: sicaolong * @Contact: [email protected] * @brief: 將陣列分割成兩部分,兩部分的和相等的部分;判斷是否存在這樣的分割 思路1:遞迴:1、先求出這個陣列的和, 2、看這個和能不能被2整除,可以的話再進行下一步返回一個嘗試分割的函式;trypartition(numbers,index,sum/2); 3、用numbers陣列的[0....index]個數字來填充 sum的揹包; 可以填充則返回true 4、tryPartition(numbers,index,sum)=tryPartition(numbers,index-1,sum)||tryPartition(numbers,index-1,sum-numbers[index]) 思路二:動態規劃: 1、同上並判斷和能否被2整除; 2、並且將揹包容量C=sum/2; 3、初始狀態:demo[j];只考慮第一個元素number[0]看看能不能填充; 4、狀態轉移;for(int i=0;i<n;++i) for(int j=C;j>=number[i];j--) memo[j]=memo[j]||memo[j-number[i]] * @TODO: */ #include<iostream> #include <vector> #include <assert.h> using namespace std; bool CanPartition(vector<int >&numbers); bool tryPartition(vector<int>&numbers, int index, int sum);//使用numbers[0........index]來填充一個容量為sum的揹包; bool CanPartition_DP(vector<int >&numbers); vector<vector<int>>memo; //memo[i][c]表示使用索引[0...i]的這些元素,是否可以完全填充一個容量為C的揹包,-1表示沒有被計算,0表示不可以填充,1表示可以填充; //=========main函式 int main() { vector<int>a = {1,5,5,11}; vector<int>b = { 1, 2, 3, 8 }; if (CanPartition(a)) cout << "存在" << endl; else cout << "不存在" << endl; if (CanPartition_DP(b)) cout << "存在" << endl; else cout << "不存在" << endl; cout<<endl; } bool CanPartition(vector<int >&numbers) { int n = numbers.size(); int sum = 0; for (int i = 0; i < n; i++) { assert(numbers[i]>0); sum += numbers[i]; } if (sum % 2 != 0) return false; memo = vector<vector<int>>(n, vector<int>(sum / 2+1,-1));//一定要多加入一列,如果不加1 會出現越界!!! return tryPartition(numbers, n - 1, sum / 2); } bool tryPartition(vector<int>&numbers, int index, int sum)//[0....index]個的number陣列的數字來填充sum揹包 { if (sum == 0) return true; if (sum < 0 || index < 0) return false; //用從0-index-1的numbers數字能不能填充這個sum的揹包,能填充,所以0-index也能填充 只不過不使用,如果不能填充,加上index能不能填充; //return tryPartition(numbers, index - 1, sum) || tryPartition(numbers, index - 1, sum - numbers[index]);//47行為遞迴用法,肯定包含重複的; if (memo[index][sum] != -1) return memo[index][sum]==1;//這裡如果等於0,返回的是false,等於1返回true memo[index][sum] = ( tryPartition(numbers, index - 1, sum) || tryPartition(numbers, index-1, sum - numbers[index]) )? 1:0; return memo[index][sum]; } bool CanPartition_DP(vector<int >&numbers) { int sum = 0; int n = numbers.size(); for (int i = 0; i < n;i++) { assert(numbers[i]>0); sum += numbers[i]; } if (sum % 2) return false;//判斷能不能被2整除 int C = sum >> 1;//揹包容量 vector<bool>memo(C + 1, false); for (int j = 0; j <= C; j++)//容量從0-C,只考慮第一個number,看看能不能填滿, memo[j] = (numbers[0] == j); for (int i = 1; i < n;i++)//從第一個開始,放,直到最後一個 for (int j = C; j >= numbers[i]; j--) memo[j] = memo[j-1] || memo[j - numbers[i]]; return memo[C]; }