39. 组合总和
组合中无重复元素,所有元素可以随便取多少次。那么startIndex就可以从本次遍历处开始。
class Solution {
public:
// 老套路,两个数组前一个存储中间结果,后一个存储总结果集vector<int> vec;vector<vector<int>> res;// 回溯void backtracking(vector<int>& candidates, int target, int startIndex){if (target == 0){res.push_back(vec);return;}// 如果小于0则表示不满足,不需要加入结果集else if (target < 0){return;}// 对于n叉树的遍历for (int i = startIndex;i<candidates.size();i++){target -= candidates[i];vec.push_back(candidates[i]);// 还是需要传递startIndex,但是下一级递归可以使用这一级的数,因为可重复backtracking(candidates, target, i);target += candidates[i];vec.pop_back();}}vector<vector<int>> combinationSum(vector<int>& candidates, int target) {backtracking(candidates, target, 0);return res;}
};
39. 组合总和
这一次变为组合中有重复元素,但是每一个元素只能使用一次。那么就需要先对组合元素排序,如果相邻元素相同只需要遍历一次,否则可能造成结果集重合。
class Solution {
public:vector<int> path;vector<vector<int>> res;void backtracking(vector<int>& candidates, int target, int startIndex){if (target == 0){res.push_back(path);return;}if (target < 0){return;}for (int i = startIndex; i<candidates.size();i++){// 这里同层的相同元素直接跳过,否则会出现重复if (i > startIndex && candidates[i] == candidates[i-1])continue;target -= candidates[i];path.push_back(candidates[i]);backtracking(candidates, target, i+1);target += candidates[i];path.pop_back();}}vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {// 这个方法需要先排序sort(candidates.begin(), candidates.end());backtracking(candidates, target,0);return res;}
};
131. 分割回文串
没想到分割回文串也是组合问题的延续。难点在于分割点的选取,子串获取,回文串判断要单独写出。总之是一道经典难题吧。还需要再练习。
class Solution {
private:
// 不会写,抄的vector<string> path;vector<vector<string>> res;void backtracking(const string& s, int startIndex){// 结束条件 startIndex表示切割的起始位置if (startIndex >= s.size()){res.push_back(path);return;}// 横向切割for (int i = startIndex; i < s.size(); i++){if (isPalindrome(s, startIndex, i)){// substr函数的参数为begin,len,表示[begin, begin+len)的子串string str = s.substr(startIndex, i - startIndex + 1);path.push_back(str);}else{continue;}// 切割点向后移动backtracking(s, i+1);// 回溯path.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) {backtracking(s, 0);return res;}
};