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; } };