39. 组合总和
题目链接: 39. 组合总和
startIndex = i
表示去掉元素集合的重复,如[2, 2, 4]
和 [4, 2, 2]
class Solution {
vector<int> path;
vector<vector<int>> res;
void backtracking(vector<int>& candidates, int target, int startIndex) {
if (target == 0) {
res.push_back(path);
return;
}
for (int i = startIndex; i < candidates.size() && target >= 0/*剪枝*/; ++i) {
path.push_back(candidates[i]);
backtracking(candidates, target - candidates[i]/*回溯*/, i/*下一组数字取值范围由它控制*/);
path.pop_back();//回溯
}
}
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
backtracking(candidates, target, 0);
return res;
}
};
40.组合总和II
题目链接:40.组合总和II
本题给的数组是有重复的数组,之前的题都是不重复的数组。因此会导致取到不同位置的相同元素导致输出结果重复。
需要在单层搜索时, 进行 横向去重
,而不是之前的 深度去重
。 当层搜索中,当前起点的深度搜索是否在被之前深度搜索包含过,如果是,跳过当前起点,遍历当层的下一个起点。
数组要排序,才能通过i > 0 && candidates[i] == candidates[i - 1]
语句查找数组中重复元素。通过辅助容器的配合达到横向去重的目的。
class Solution {
vector<int> path;
vector<vector<int>> res;
void backtracking(vector<int>& candidates, int target, int startIndex, vector<bool>& used) {
if (target == 0) {
res.push_back(path);
return;
}
for (int i = startIndex; i < candidates.size() && target >= 0; ++i) {
if (i > 0 && candidates[i] == candidates[i - 1] && !used[i - 1])
continue;
path.push_back(candidates[i]);
used[i] = true;
backtracking(candidates, target - candidates[i], i + 1, used);
used[i] = false;
path.pop_back();
}
}
public:
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
vector<bool> used(candidates.size(), false);
sort(candidates.begin(), candidates.end());
backtracking(candidates, target, 0, used);
return res;
}
};
其实,也可以使用startIndex
来去重。
class Solution {
vector<int> path;
vector<vector<int>> res;
void backtracking(vector<int>& candidates, int target, int startIndex) {
if (target == 0) {
res.push_back(path);
return;
}
for (int i = startIndex; i < candidates.size() && target >= 0; ++i) {
if (i > startIndex && candidates[i - 1] == candidates[i])
continue;//跳过当前起点,到下一个起点
path.push_back(candidates[i]);
backtracking(candidates, target - candidates[i], i + 1);
path.pop_back();
}
}
public:
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
backtracking(candidates, target, 0);
return res;
}
};
131.分割回文串
题目链接: 131.分割回文串
终止条件几乎不改变,还是res.push_back(path);
,在单层搜索中,再判断是否为符合题意的path
通过startIndex
和i
来控制分割区间
class Solution {
vector<string> path;
vector<vector<string>> res;
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)/*[startIndex, i]是分割区间*/)
path.push_back(s.substr(startIndex, i - startIndex + 1/*substr第二个参数是子串的长度,长度至少为1*/));
else
continue;
backtracking(s, i + 1);
path.pop_back();
}
}
bool isPalindrome(const std::string& s, int l, int r) {//回文子串
while (l < r) {
if (s[l] == s[r]) {
l++;
r--;
} else
return false;
}
return true;
}
public:
vector<vector<string>> partition(string s) {
backtracking(s, 0);
return res;
}
};