回溯模版
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
}
class Solution {
public:
vector<vector<int>> result;
vector<int> vec;
void backtracking(int n,int k,int startIndex){
if(vec.size() == k){
result.push_back(vec);
return;
}
for(int i=startIndex;i<=n;i++){
vec.push_back(i);
backtracking(n,k,i+1);
vec.pop_back();
}
}
vector<vector<int>> combine(int n, int k) {
backtracking(n,k,1);
return result;
}
};
剪枝优化
class Solution {
private:
vector<vector<int>> result;
vector<int> path;
void backtracking(int n, int k, int startIndex) {
if (path.size() == k) {
result.push_back(path);
return;
}
for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) { // 优化的地方
path.push_back(i); // 处理节点
backtracking(n, k, i + 1);
path.pop_back(); // 回溯,撤销处理的节点
}
}
public:
vector<vector<int>> combine(int n, int k) {
backtracking(n, k, 1);
return result;
}
};
class Solution {
public:
vector<vector<int>> result;
vector<int> vec;
void backtracking(int k,int n,int sum,int startIndex){
if (sum > n) { // 剪枝操作
return;
}
if(vec.size() == k){
if(sum == n)
result.push_back(vec);
return;
}
for(int i=startIndex;i<= 10 - (k - vec.size());i++){
vec.push_back(i);
backtracking(k,n,sum+i,i+1);
vec.pop_back();
}
}
vector<vector<int>> combinationSum3(int k, int n) {
backtracking(k,n,0,1);
return result;
}
};
class Solution {
public:
vector<string> letter={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
vector<string> result;
string path;
void backtracking(string digits,int index){
if(index == digits.size()){
if(path.size())
result.push_back(path);
return;
}
int num = digits[index] - '0';
for(int i=0;i<letter[num].size();i++){
path.push_back(letter[num][i]);
backtracking(digits,index+1);
path.pop_back();
}
}
vector<string> letterCombinations(string digits) {
backtracking(digits,0);
return result;
}
};
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& candidates,int index,int sum,int target){
if(sum > target)
return;
else if(sum == target){
result.push_back(path);
return;
}
for(int i=index;i<candidates.size();i++){
path.push_back(candidates[i]);
backtracking(candidates,i,sum+candidates[i],target);
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
backtracking(candidates,0,0,target);
return result;
}
};
用used数组去重
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int> candidates,int index,int sum,int target,vector<bool>& used){
if(sum > target)
return;
else if(sum == target){
result.push_back(path);
return;
}
for(int i=index;i<candidates.size();i++){
if(i && candidates[i]==candidates[i-1] && used[i-1]==false)
continue;
path.push_back(candidates[i]);
used[i]=true;
backtracking(candidates,i+1,sum+candidates[i],target,used);
path.pop_back();
used[i]=false;
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
vector<bool> used(candidates.size(), false);
sort(candidates.begin(),candidates.end());
backtracking(candidates,0,0,target,used);
return result;
}
};
直接去重
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int> candidates,int index,int sum,int target){
if(sum > target)
return;
else if(sum == target){
result.push_back(path);
return;
}
for(int i=index;i<candidates.size();i++){
if(i>index && candidates[i]==candidates[i-1])
continue;
path.push_back(candidates[i]);
backtracking(candidates,i+1,sum+candidates[i],target);
path.pop_back();
}
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(),candidates.end());
backtracking(candidates,0,0,target);
return result;
}
};
class Solution {
public:
vector<vector<string>> result;
vector<string> path;
bool isPalindrome(string s){
string tmp(s.rbegin(),s.rend());
return s == tmp;
}
void backtracking(string s,int index){
if(index >= s.size()){
bool flag = true;
for(auto it:path){
if(!isPalindrome(it))
flag = false;
}
if(flag)
result.push_back(path);
return;
}
for(int i=index;i<s.size();i++){
path.push_back(s.substr(index,i-index+1));
backtracking(s,i+1);
path.pop_back();
}
}
vector<vector<string>> partition(string s) {
backtracking(s,0);
return result;
}
};
class Solution {
public:
vector<string> result;
vector<int> path;
void backbracking(string s,int index){
if(path.size() >= 4){
string tmp = to_string(path[0]) + "." + to_string(path[1]) + "." + to_string(path[2]) + "." + to_string(path[3]);
if(tmp.size() == s.size()+3)
result.push_back(tmp);
return;
}
for(int i=index;i<s.size();i++){
int tmp = stoi(s.substr(index,i-index+1));
if(tmp<0 || tmp>255)
return;
path.push_back(tmp);
backbracking(s,i+1);
path.pop_back();
}
}
vector<string> restoreIpAddresses(string s) {
backbracking(s,0);
return result;
}
};
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int> nums,int index){
result.push_back(path);
for(int i=index;i<nums.size();i++){
path.push_back(nums[i]);
backtracking(nums,i+1);
path.pop_back();
}
}
vector<vector<int>> subsets(vector<int>& nums) {
backtracking(nums,0);
return result;
}
};
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int> nums,int index){
result.push_back(path);
for(int i=index;i<nums.size();i++){
if(i>index && nums[i] == nums[i-1])
continue;
path.push_back(nums[i]);
backtracking(nums,i+1);
path.pop_back();
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(),nums.end());
backtracking(nums,0);
return result;
}
};
对回溯结果进行去重
class Solution {
public:
set<vector<int>> result;
vector<int> path;
void backtracking(vector<int> nums,int index){
if(path.size() > 1)
result.insert(path);
for(int i=index;i<nums.size();i++){
if(path.size() && nums[i]<path.back())
continue;
path.push_back(nums[i]);
backtracking(nums,i+1);
path.pop_back();
}
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
backtracking(nums,0);
vector<vector<int>> res(result.begin(),result.end());
return res;
}
};
单层去重
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int> nums,int index){
if(path.size() > 1)
result.push_back(path);
unordered_set<int> set;
for(int i=index;i<nums.size();i++){
if(path.size() && nums[i]<path.back() || set.find(nums[i])!=set.end())
continue;
set.insert(nums[i]);
path.push_back(nums[i]);
backtracking(nums,i+1);
path.pop_back();
}
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
backtracking(nums,0);
return result;
}
};
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int> nums,vector<bool> used){
if(path.size() == nums.size()){
result.push_back(path);
return;
}
for(int i=0;i<nums.size();i++){
if(used[i])
continue;
used[i]=true;
path.push_back(nums[i]);
backtracking(nums,used);
path.pop_back();
used[i]=false;
}
}
vector<vector<int>> permute(vector<int>& nums) {
vector<bool> used(nums.size(),false);
backtracking(nums,used);
return result;
}
};
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int> nums,vector<bool> used){
if(path.size() == nums.size()){
result.push_back(path);
return;
}
for(int i=0;i<nums.size();i++){
if(i && nums[i]==nums[i-1] && used[i-1]==false || used[i])
continue;
used[i]=true;
path.push_back(nums[i]);
backtracking(nums,used);
path.pop_back();
used[i]=false;
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<bool> used(nums.size(),false);
sort(nums.begin(),nums.end());
backtracking(nums,used);
return result;
}
};
class Solution {
public:
unordered_map<string, map<string, int>> targets;
vector<string> result;
bool backtracking(vector<vector<string>> tickets){
if(result.size() == tickets.size()+1){
return true;
}
for(auto& it:targets[result[result.size()-1]]){
if(it.second){
result.push_back(it.first);
it.second--;
if(backtracking(tickets))
return true;
result.pop_back();
it.second++;
}
}
return false;
}
vector<string> findItinerary(vector<vector<string>>& tickets) {
for(auto it:tickets){
targets[it[0]][it[1]]++;
}
result.push_back("JFK");
backtracking(tickets);
return result;
}
};
class Solution {
public:
vector<vector<string>> result;
bool isValid(int row,int col,vector<string> path,int n){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i == row || j == col || i-row == j-col || i-row == col-j){
if(path[i][j] == 'Q')
return false;
}
}
}
return true;
}
void backtracking(int n,int row,vector<string>& path){
if(row == n){
result.push_back(path);
return;
}
for(int j=0;j<n;j++){
if(isValid(row,j,path,n)){
path[row][j]='Q';
backtracking(n,row+1,path);
path[row][j]='.';
}
}
}
vector<vector<string>> solveNQueens(int n) {
vector<string> path(n, string(n, '.'));
backtracking(n,0,path);
return result;
}
};
class Solution {
public:
bool isValid(vector<vector<char>> board,int row,int col,char k){
for(int i=0;i<9;i++){
if(board[row][i]==k || board[i][col]==k)
return false;
}
int starti = row/3*3,startj = col/3*3;
for(int i=starti;i<starti+3;i++){
for(int j=startj;j<startj+3;j++){
if(board[i][j] == k)
return false;
}
}
return true;
}
bool backbracking(vector<vector<char>>& board){
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
if(board[i][j] == '.'){
for(int k=1;k<10;k++){
if(isValid(board,i,j,k+'0')){
board[i][j] = k+'0';
if(backbracking(board)) return true;
board[i][j] = '.';
}
}
return false;
}
}
}
return true;
}
void solveSudoku(vector<vector<char>>& board) {
backbracking(board);
}
};
回溯算法能解决如下问题:
组合问题:N个数里面按一定规则找出k个数的集合
排列问题:N个数按一定规则全排列,有几种排列方式
切割问题:一个字符串按一定规则有几种切割方式
子集问题:一个N个数的集合里有多少符合条件的子集
棋盘问题:N皇后,解数独等等