文章链接:代码随想录
题目链接:39. 组合总和
思路:和组合问题的不同在于这里的元素不重复但可以重复选取,startIndex设为i。
未剪枝:
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
void backtracking(vector<int>& candidates, int target, int sum, int startIndex){
if (sum == target){
res.push_back(path);
return ;
}
else if (sum > target) {
return ;
}
for (int i = startIndex; i < candidates.size(); i++){
path.push_back(candidates[i]);
backtracking(candidates, target, sum + candidates[i], i);
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
backtracking(candidates, target, 0, 0);
return res;
}
};
排序后剪枝:
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
void backtracking(vector<int>& candidates, int target, int sum, int startIndex){
if (sum == target){
res.push_back(path);
return ;
}
for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++){
path.push_back(candidates[i]);
backtracking(candidates, target, sum + candidates[i], i);
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
backtracking(candidates, target, 0, 0);
return res;
}
};
文章链接:代码随想录
题目链接:40.组合总和II
思路:与上一题不同在于元素右重复但不可以重复选取,若用上一题的方法可能会导致有重复答案出现。去重的逻辑在于纵向(树枝)不去重,横向(数层)去重;也就是递归不去重,在for循环中去重。注意需要先对数组排序。
利用used数组去重:
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
void backtracking(vector<int>& candidates, int target, int sum, int startIndex,vector<bool>& used){
if (sum == target){
res.push_back(path);
return ;
}
for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++){
if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) continue;
path.push_back(candidates[i]);
used[i] = true;
backtracking(candidates, target, sum + candidates[i], i + 1, used);
used[i] = false;
path.pop_back();
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
vector<bool> used(candidates.size(), false);
sort(candidates.begin(), candidates.end());
backtracking(candidates, target, 0, 0, used);
return res;
}
};
利用startIndex去重(感觉这种方法更容易理解些,写起来也简便些):
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
void backtracking(vector<int>& candidates, int target, int sum, int startIndex){
if (sum == target){
res.push_back(path);
return ;
}
for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++){
if (i > startIndex && candidates[i] == candidates[i - 1]) continue;
path.push_back(candidates[i]);
backtracking(candidates, target, sum + candidates[i], i + 1);
path.pop_back();
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
backtracking(candidates, target, 0, 0);
return res;
}
};
文章链接:代码随想录
题目链接:131.分割回文串
思路:重点在于理解题意,判断一段是回文串就找下一个切割线,不是就把这个切割线开始的切割范围向后挪,如果切割线(也就是startIndex)能够走到字符串最后,说明找到了一组结果;如果切割范围挪到最后也不是回文串,res将不会收录这组path里的数据,path的数据会pop_back()出去并把切割线(startIndex)位置向后挪。(这里有点绕,思考了好一会,感觉干想会很头痛,边把思路写出来边想会理解的快一些)
class Solution {
public:
vector<vector<string>> res;
vector<string> path;
void backtracking(const string& s, int startIndex){
if (startIndex >= s.size()){
res.push_back(path);
return ;
}
for(int i = startIndex; i <= s.size(); i++){
if (isPalindrome(s, startIndex, i)){
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;
}
vector<vector<string>> partition(string s) {
backtracking(s, 0);
return res;
}
};
另外这里判断回文串的方法没看动态规划的那种,等刷到动态规划再回来写一下。
第二十六天休息,第二十七天打卡,昨晚半夜醒了没睡着,今天上午一直在睡,也没健身,希望今天睡眠好一些。
加油!!!