Leetcode Combination Sum I,II,III 均是dfs + backtraing 模板題目,適合集中練習數組
Leetcode - 039. Combination Sumcode
個人思路:
1.排序是必要的,爲何排序是必要的?考慮到咱們dfs + backtraing 的標準三步(1.優先斷定可行解 2.剪枝 3.遍歷下行狀態,更新backtracing的追蹤變量),咱們如何斷定是一個可行解,顯然是當前sum = target,那麼若是咱們不排序的話當前sum > target 還有可能pop 最後一個元素而後與以後較小的元素造成可行解,這樣帶來了沒必要要的麻煩並且沒法剪枝,因此咱們應該排序原數組
2.遵循標準三步,注意是可重複的peek,那麼每次的下行狀態包括當前狀態的終止位置排序
class Solution { public: void dfs(vector<vector<int>> &vct, vector<int> &cur, vector<int>& nums, const int target, int cursum, int index) { if (cursum == target) { vct.push_back(cur); return; } int n = nums.size(); if (cursum > target || index >= n) return; for (int i = index; i < n; ++i) { cur.push_back(nums[i]); dfs(vct, cur, nums, target, cursum + nums[i], i); cur.pop_back(); } } vector<vector<int>> combinationSum(vector<int>& candidates, int target) { vector<vector<int>> vct; vector<int> cur; if (candidates.size() <= 0) return vct; sort(candidates.begin(), candidates.end()); dfs(vct, cur, candidates, target, 0, 0); return vct; } };
Leetcode - 040. Combination Sum IIip
個人思路:
1.主體思路與Combination Sum 是一致的
2.有重複元素
3.元素只能使用一次
這裏的去重操做須要技巧:
首先,每一個元素(無論是否與其餘元素相等)只能使用一次,能夠用used數組標識
考慮到樣例中給出的 1 + 1 + 6 = 8,不能單純的後置元素等於前置元素去重,那咱們考慮何時重複?
假設樣本[1,1,1,3] , target = 5, 那麼解爲[1,1,3]
根據深搜的性質,必定是index = 0,1,3的元素組成了解,那麼咱們能夠了解到的是,當元素存在前置等值元素且其前置等值元素還未被使用時就使用當前元素必然會發生重複解。瞭解這一點,稍做判斷修改便可ACci
class Solution { public: void dfs(vector<vector<int>> &vct, vector<int> cur, vector<int>& nums, vector<int>& used, const int target, int cursum, int index) { if (cursum == target) { vct.push_back(cur); return; } int n = nums.size(); if (cursum > target || index >= n) return; for (int i = index + 1; i < n; ++i) { int j = i - 1; int placable = 1; while (j >= 0 && nums[j] == nums[i]) { if (used[i] == 0) { placable = 0; break; } } if (placable == 0) continue; used[i] = 1; cur.push_back(nums[i]); dfs(vct, cur, nums, used, target, cursum + nums[i], i + 1); cur.pop_back(); used[i] = 0; } } vector<vector<int>> combinationSum2(vector<int>& candidates, int target) { vector<vector<int>> vct; vector<int> cur; int n = candidates.size(); if (n <= 0) return vct; vector<int> used(n, 0); sort(candidates.begin(), candidates.end()); dfs(vct, cur, candidates, used,target, 0, 0); return vct; } };
Leetcode - 216. Combination Sum IIIleetcode
個人思路:
1.使用k個1 - 9之間的正整數組成target,主體思路同上
2.剪枝的時候多加一個當前解空間的大小判斷一下便可,論起來比起Combination Sum II還要容易一些get
class Solution { public: void dfs(vector<vector<int>> &vct, vector<int> &cur, vector<int> &nums, int k, int n, int index, int cursum) { if (int(cur.size()) == k && cursum == n) { vct.push_back(cur); return; } // 注意這裏能夠取等和不能取等的 if (int(cur.size()) >= k || cursum >= n || index > 9) return; for (int i = index; i <= 9; ++i) { cur.push_back(i); dfs(vct, cur, nums, k, n, i + 1, cursum + i); cur.pop_back(); } } vector<vector<int>> combinationSum3(int k, int n) { vector<vector<int>> vct; vector<int> cur; vector<int> nums{ 0,1,2,3,4,5,6,7,8,9 }; dfs(vct, cur, nums, k, n, 1, 0); return vct; } };