39.组合总和
代码随想录链接
题目
LeetCode-39.组合总和
给定一个没有重复元素的数组, 在可重复选取元素的情况下,
返回所有之和等于目标值的组合,
组合与组合之间包含的不同数字的个数必须是不同的.
自己的想法
就模板题, 按照回溯法总结的模板就可以.
题解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class Solution { private: vector<vector<int>> result; vector<int> current; int sum = 0; void backtracing(vector<int> &candidates, int target, int startIndex) { if (sum >= target) { if (sum == target) result.push_back(current); return; }
for (int i = startIndex; i < candidates.size(); i++) { sum += candidates[i]; current.push_back(candidates[i]); backtracing(candidates, target, i); sum -= candidates[i]; current.pop_back(); } } public: vector<vector<int>> combinationSum(vector<int>& candidates, int target) { backtracing(candidates, target, 0); return this -> result; } };
|
40.组合总和II
代码随想录链接
题目
LeetCode-40.组合总和II
和上题类似, 不过可以出现重复元素, 且不同位置的元素只能被选中一次.
自己的想法
直接把上题的答案拿过来是不行的,
因为要考虑位置不同的相同元素在回溯时会产生的相同组合.
可以将相同的元素排在一起, 也就是排序, 然后再通过额外的变量,
保证两个相同的元素只出现一次时, 只考虑一遍情况.
题解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| class Solution { private: vector<vector<int>> result; vector<int> current; int sum = 0; void backtracing(vector<int> &candidates, int target, int startIndex, vector<bool> &used) { if (sum > target) return; if (sum == target) { result.push_back(current); return; }
for (int i = startIndex; i < candidates.size(); i++) { if (i > 0 && candidates[i] == candidates[i - 1] && !used[i - 1]) continue;
sum += candidates[i]; used[i] = true; current.push_back(candidates[i]); backtracing(candidates, target, i + 1, used); sum -= candidates[i]; used[i] = false; current.pop_back(); } } public: vector<vector<int>> combinationSum2(vector<int>& candidates, int target) { vector<bool> used(candidates.size(), false); sort(candidates.begin(), candidates.end()); backtracing(candidates, target, 0, used); return this -> result; } };
|
131.分割回文串
代码随想录链接
题目
LeetCode-131.分割回文串
给定一个字符串, 要求返回所有分割方式,
每种分割方式内的分割出的子串都是回文.
自己的想法
刚开始懵了. 真的不知道咋写.但是毕竟知道是要拿回溯法写
分割字符串和上面的取组合其实是类似的.
for循环横向遍历的是当前字符串不断从startIndex开始向右延长,
纵向递归的是对剩下的字符串进行分割.
在分割的过程中如果一种分割方法产生的子串不是回文,
则应该立即结束这种分割方式, 不应进行纵向递归.
题解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Solution { private: vector<vector<string>> result; vector<string> current; void backtracing(const string &s, int startIndex) { if (startIndex >= s.size()) { result.push_back(current); return; }
for (int i = startIndex; i < s.size(); i++) { if (isPalindrome(s, startIndex, i)) { current.push_back(s.substr(startIndex, i - startIndex + 1)); } else continue; backtracing(s, i + 1); current.pop_back(); } }
bool isPalindrome(const string &s, int start, int end) { for (int i = start, j = end; i < j; i++, j--) { if (s[i] != s[j]) return false; } return true; } public: vector<vector<string>> partition(string s) { backtracing(s, 0); return result; } };
|