回溯算法复习
1.组合问题:
- 77. 组合
- 39. 组合总和
- 40. 组合总和 II
//关键问题还是在这里,由于出现重复的结果,需要在遍历过程中解决重复问题
//在同一层中,该元素与上一个元素相同,且上一个元素的结果已经处理完了,那么可以直接跳过当前元素,以避免重复
//used[j-1]==false表明上一个元素已经处理完成(回溯恢复状态为false) - 216. 组合总和 III
class Solution {
public:
//两个数据结构,分别存每一次的组合、所有的组合结果
vector<int> path;
vector<vector<int>> result;
//void 无返回值 ,参数需要 数据总数、截止条件、起始下标
void backtracking(int n,int k,int i) {
//递归终止条件,为真则把path写入到result中
if(path.size()==k) {
result.push_back(path);
return;
}
//处理元素集合(横向,处理一层的元素结合),从起始下标i开始
for(int j=i;j<=n;j++) {
//path中写入
path.push_back(j);
//下一个点从j+1开始
backtracking(n,k,j+1); //递归,纵向遍历
//回溯,弹出
path.pop_back();
}
}
vector<vector<int>> combine(int n, int k) {
backtracking(n,k,1);
return result;
}
};
class Solution {
public:
vector<int> path;
vector<vector<int>> result;
int sum=0;
void backtracking(vector<int>& candidates, int target, int sum, int startIndex) {
if(sum>target)
return;
if(sum==target) {
result.push_back(path);
return;
}
for(int j=startIndex;j<candidates.size();j++) {
path.push_back(candidates[j]);
sum+=candidates[j];
backtracking(candidates,target,sum,j);
sum-=candidates[j];
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
backtracking(candidates,target,0,0);
return result;
}
};
class Solution {
public:
vector<int> path;
vector<vector<int>> result;
int sum=0;
void backtracking(vector<int>& candidates, int target, int sum, int startIndex,vector<bool>& used) {
if(sum==target) {
result.push_back(path);
return;
}
for(int j=startIndex;j<candidates.size() && sum<=target;j++) {
//关键问题还是在这里,由于出现重复的结果,需要在遍历过程中解决重复问题
//在同一层中,该元素与上一个元素相同,且上一个元素的结果已经处理完了,那么可以直接跳过当前元素,以避免重复
//used[j-1]==false表明上一个元素已经处理完成(回溯恢复状态为false)
if(j>0 && candidates[j]==candidates[j-1] && used[j-1]==false) {
continue;
}
path.push_back(candidates[j]);
sum+=candidates[j];
used[j]=true;
backtracking(candidates,target,sum,j+1,used);
sum-=candidates[j];
path.pop_back();
used[j]=false;
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
//排序方便处理相同相邻元素,
sort(candidates.begin(),candidates.end());
//需要一个used数组来记录元素的使用情况
vector<bool> used(candidates.size(),false);
backtracking(candidates,target,0,0,used);
return result;
}
};
class Solution {
public:
vector<int> path;
vector<vector<int>> result;
int sum=0;
void backtracking(int n,int k,int sum, int start) {
if(sum==n && path.size()==k) {
result.push_back(path);
return;
}
for(int i=start;i<=9;i++) {
sum+=i;
path.push_back(i);
backtracking(n,k,sum,i+1);
sum-=i;
path.pop_back();
}
}
vector<vector<int>> combinationSum3(int k, int n) {
backtracking(n,k,0,1);
return result;
}
};
class Solution {
public:
//取数字的个数等于digits的长度,终止
//需要一个参数index来指明到哪个数字区域,取出对应的字符集,放入for循环中
const string letterMap[10] = {
"",
"",
"abc",
"def",
"ghi",
"jkl",
"mno",
"pqrs",
"tuv",
"wxyz"
};
string s;
vector<string> result;
void backtracking(const string& digits, int index) {
if(index == digits.size()) {
result.push_back(s);
return;
}
int digit = digits[index]-'0';
string letters = letterMap[digit];
for(int i=0;i<letters.size();i++) {
s.push_back(letters[i]);
backtracking(digits,index+1);
s.pop_back();
}
}
vector<string> letterCombinations(string digits) {
if(digits.empty()) {
return result;
}
backtracking(digits,0);
return result;
}
};
2.分割问题
1).在字符串中插入元素: s.insert(s.begin()+i+1,‘.’);
在字符串中消除元素: s.erase(s.begin()+i+1);
2).数字字符串转为int:
int num=0;
for(int i=start;i<=end;i++) {
num = num*10+(s[i]-‘0’);
}
class Solution {
public:
vector<vector<string>> res;
vector<string> path;
bool judge(string& s,int begin,int end) {
for(int i=begin,j=end;i<j;i++,j--) {
if(s[i]!=s[j]) {
return false;
}
}
return true;
}
void backtracking(string& s,int startIndex) {
if(startIndex == s.size()) {
res.push_back(path);
return;
}
for(int i=startIndex;i<s.size();i++) {
if(judge(s,startIndex,i)) {
string str = s.substr(startIndex,i-startIndex+1);
path.push_back(str);
}else {
continue;
}
backtracking(s,i+1);
path.pop_back();
}
}
vector<vector<string>> partition(string s) {
backtracking(s,0);
return res;
}
};
1.在字符串中插入元素:
s.insert(s.begin()+i+1,‘.’);
在字符串中消除元素
s.erase(s.begin()+i+1);
2.数字字符串转为int:
int num=0;
for(int i=start;i<=end;i++) {
num = num*10+(s[i]-‘0’);
}
class Solution {
public:
vector<string> res;
bool judge(const string& s,int start,int end) {
if(start > end) {
return false;
}
if(s[start]=='0' && start!=end) {
return false;
}
int num = 0;
for(int i=start;i<=end;i++) {
if(s[i]>'9' || s[i] < '0') {
return false;
}
num = num*10+(s[i]-'0');
if(num>255)
return false;
}
}
void backtracking(string& s,int start,int pointNum) {
if(pointNum == 3) {
if(judge(s,start,s.size()-1)) {
res.push_back(s);
}
return;
}
for(int i=start;i<s.size();i++) {
if(judge(s,start,i)) {
s.insert(s.begin()+i+1,'.');
pointNum++;
backtracking(s,i+2,pointNum);
pointNum--;
s.erase(s.begin()+i+1);
}else
break;
}
}
vector<string> restoreIpAddresses(string s) {
backtracking(s,0,0);
return res;
}
};