小結:
組合總和系列的題,題目都是一個套路,都是需要另寫一個遞歸函數,這里我們新加入三個變量,start記錄當前的遞歸到的下標,out為一個解,res保存所有已經得到的解,每次調用新的遞歸函數時,此時的target要減去當前數組的的數。
1、39. 組合總和
給定一個無重復元素的數組 candidates
和一個目標數 target
,找出 candidates
中所有可以使數字和為 target
的組合。
candidates
中的數字可以無限制重復被選取。
說明:
- 所有數字(包括
target
)都是正整數。 - 解集不能包含重復的組合。
示例 1:
輸入: candidates =[2,3,6,7],
target =7
, 所求解集為: [ [7], [2,2,3] ]
示例 2:
輸入: candidates = [2,3,5],
target = 8,
所求解集為:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
class Solution { public: vector<vector<int>> combinationSum(vector<int>& nums, int target) { vector<vector<int>> res; if(nums.empty()) return res; vector<int> temp; sort(nums.begin(),nums.end());//對數組進行排序 combinationDfs(nums,0,target,temp,res); return res; } void combinationDfs(vector<int> &nums,int pos,int target,vector<int> &temp, vector<vector<int>> &res) { if(target<0) return; else if(target==0) { res.push_back(temp); return; } else { for(int i=pos;i<nums.size();++i)//數字可以重復使用,注意i的起始位置 { temp.push_back(nums[i]); combinationDfs(nums,i,target-nums[i],temp,res); temp.pop_back(); } } } };
2、40. 組合總和 II
給定一個數組 candidates
和一個目標數 target
,找出 candidates
中所有可以使數字和為 target
的組合。
candidates
中的每個數字在每個組合中只能使用一次。
說明:
- 所有數字(包括目標數)都是正整數。
- 解集不能包含重復的組合。
示例 1:
輸入: candidates =[10,1,2,7,6,1,5]
, target =8
, 所求解集為: [ [1, 7], [1, 2, 5], [2, 6], [1, 1, 6] ]
示例 2:
輸入: candidates = [2,5,2,1,2], target = 5, 所求解集為: [ [1,2,2], [5] ]
與上一道本質沒有區別,只需要改動一點點即可,之前那道題給定數組中的數字可以重復使用,而這道題不能重復使用,只需要在之前的基礎上修改兩個地方即可,首先在遞歸的for循環里加上if (i > start && num[i] == num[i - 1]) continue; 這樣可以防止res中出現重復項,然后就在遞歸調用combinationSum2DFS里面的參數換成i+1,這樣就不會重復使用數組中的數字了,
class Solution { public: vector<vector<int>> combinationSum2(vector<int>& nums, int target) { vector<vector<int>> res; if(nums.empty()) return res; vector<int> temp; sort(nums.begin(),nums.end()); combinationDfs(nums,0,target,temp,res); return res; } void combinationDfs(vector<int> &nums,int pos,int target,vector<int> &temp, vector<vector<int>> &res) { if(target<0) return; else if(target==0) { res.push_back(temp); return; } else { for(int i=pos;i<nums.size();++i) { if(i>pos && nums[i]==nums[i-1]) //注意此處 i>pos continue; temp.push_back(nums[i]); combinationDfs(nums,i+1,target-nums[i],temp,res); temp.pop_back(); } } } };
3、216. 組合總和 III
找出所有相加之和為 n 的 k 個數的組合。組合中只允許含有 1 - 9 的正整數,並且每種組合中不存在重復的數字。
說明:
- 所有數字都是正整數。
- 解集不能包含重復的組合。
示例 1:
輸入: k = 3, n = 7 輸出: [[1,2,4]]
示例 2:
輸入: k = 3, n = 9 輸出: [[1,2,6], [1,3,5], [2,3,4]]
這道題題是組合之和系列的第三道題,跟之前兩道Combination Sum 組合之和,Combination Sum II 組合之和之二都不太一樣,那兩道的聯系比較緊密,變化不大,而這道跟它們最顯著的不同就是這道題的個數是固定的,為k。個人認為這道題跟那道Combinations 組合項更相似一些,但是那道題只是排序,對k個數字之和又沒有要求。所以實際上這道題是它們的綜合體,兩者雜糅到一起就是這道題的解法了,n是k個數字之和,如果n小於0,則直接返回,如果n正好等於0,而且此時out中數字的個數正好為k,說明此時是一個正確解,將其存入結果res中,
class Solution { public: vector<vector<int>> combinationSum3(int k, int n) { vector<vector<int>> res; if(k<=0 || n<=0) return res; vector<int> temp; combinationDfs(k,1,n,temp,res); return res; } void combinationDfs(int k,int pos,int n,vector<int> &temp, vector<vector<int>> &res) { if(n<0) return; else if(k == temp.size() && n==0) { res.push_back(temp); return; } else { for(int i=pos;i<=9;++i) { temp.push_back(i); combinationDfs(k,i+1,n-i,temp,res); temp.pop_back(); } } } };