回溯
火柴拼正方形
class Solution {
public:
//4个集合
int sum[4];
bool res=false;
void backtracking(vector<int>&mat,int a,int index){//回溯超时了
//剪枝
if(res)return;//已经找到一种拼接方法,直接返回
if(index==mat.size()){//火柴都遍历完了,每根火柴都只属于一个集合
if(sum[0]==a&&sum[1]==a&&sum[2]==a&&sum[3]==a){
res|=true;
}
return;
}
//mat[index]可以尝试加入每一个集合
for(int i=0;i<4;++i){
if(sum[i]+mat[index]<=a){//mat[index]可以加入集合i
sum[i]+=mat[index];
backtracking(mat,a,index+1);
sum[i]-=mat[index];//回溯
}
}
}
bool dfs(vector<int>&mat,int a,int index,int sum1,int sum2,int sum3,int sum4){
if(index==mat.size()){
if(sum1==a&&sum2==a&&sum3==a&&sum4==a){
return true;
}
return false;
}
if(sum1>a||sum2>a||sum3>a||sum4>a){
return false;
}
return dfs(mat,a,index+1,sum1+mat[index],sum2,sum3,sum4)||
dfs(mat,a,index+1,sum1,sum2+mat[index],sum3,sum4)||
dfs(mat,a,index+1,sum1,sum2,sum3+mat[index],sum4)||
dfs(mat,a,index+1,sum1,sum2,sum3,sum4+mat[index]);
}
bool makesquare(vector<int>& matchsticks) {
int sum=0;
for(int x:matchsticks){
sum+=x;
}
if(sum%4!=0)return false;
int a=(sum>>2);//正方形边长
// backtracking(matchsticks,a,0);//回溯超时 通过了176/183个样例
//dfs必须加降序才能不超时 s
sort(matchsticks.begin(),matchsticks.end(),[&](int& a,int& b){return a>b;});
// return dfs(matchsticks,a,0,0,0,0,0);
backtracking(matchsticks,a,0);
return res;
}
};
字母大小写全排列
class Solution {
public:
vector<string>res;
string path;
void backtracking(string s,int curIndex){
if(curIndex==s.length()){
res.push_back(path);
return;
}
if(s[curIndex]>='0'&&s[curIndex]<='9'){
path+=s[curIndex];
backtracking(s,curIndex+1);
}
else if(s[curIndex]>='a'&&s[curIndex]<='z'){
path+=s[curIndex];
int l=path.length()-1;
backtracking(s,curIndex+1);
path=path.substr(0,l);
path+=s[curIndex]-32;
l=path.length()-1;
backtracking(s,curIndex+1);
path=path.substr(0,l);
}else{
path+=s[curIndex];
int l=path.length()-1;
backtracking(s,curIndex+1);
path=path.substr(0,l);
path+=s[curIndex]+32;
l=path.length()-1;
backtracking(s,curIndex+1);
path=path.substr(0,l);
}
}
vector<string> letterCasePermutation(string s) {
backtracking(s,0);
return res;
}
};
优美的排列
class Solution {
public:
int res=0;
vector<bool>vis;
void backtracking(int n,int curIndex){
if(curIndex>n){
res++;
return;
}
//只要进入递归,说明1~curIndex都是满足要求的
for(int i=1;i<=n;++i){
if(!vis[i]){
if(curIndex%i==0||i%curIndex==0){
vis[i]=true;
backtracking(n,curIndex+1);
vis[i]=false;//回溯
}
}
}
}
int countArrangement(int n) {
vis.resize(n+1,0);
backtracking(n,1);
return res;
}
};
活字印刷
class Solution {
public:
int res=0;
// string path;
vector<int>cnt;//统计字母的频次
void backtracking(string titles){
//当前层遍历每个字母,每个字母可以选,也可以不选
//递归终止条件就是26个大写字母都用完了
for(int i=0;i<26;++i){
if(cnt[i]==0){
continue;
}
// path+=i+'A';
cnt[i]--;
backtracking(titles);
// path=path.substr(0,path.length()-1);
res++;
cnt[i]++;//回溯
}
}
int numTilePossibilities(string tiles) {
cnt.resize(26,0);
for(char ch:tiles){
cnt[ch-'A']++;
}
backtracking(tiles);
return res;
}
};
列举单词的全部缩写
class Solution {
public:
vector<string>res;
string path;
void backtracking(string word,int startIndex){
if(startIndex>=word.length()){
res.push_back(path);
return;
}
//当前位置可以选择不缩写
path+=word[startIndex];
backtracking(word,startIndex+1);
path=path.substr(0,path.length()-1);
//当前位置可以选择缩写
for(int i=startIndex;i<word.length();++i){
stringstream ss;
string s;
int val=i-startIndex+1;
ss<<val;
ss>>s;
if(i+1<word.length()){
s+=word[i+1];
}
path+=s;
backtracking(word,i+2);
path=path.substr(0,path.length()-s.length());
}
}
vector<string> generateAbbreviations(string word) {
backtracking(word,0);
return res;
}
};
分割回文串
class Solution {
public:
vector<vector<string>>res;
vector<string>path;
void backtracking(string s,int startIndex){
if(startIndex==s.length()){
res.push_back(path);
return;
}
for(int i=startIndex;i<s.length();++i){
if(isHuiWen(s,startIndex,i)){
path.push_back(s.substr(startIndex,i-startIndex+1));
backtracking(s,i+1);
path.pop_back();
}
}
}
bool isHuiWen(string s,int l,int r){
if(l==r)return true;
int left=l;
int right=r;
while(left<=right){
if(s[left]!=s[right]){
return false;
}
++left;
--right;
}
return true;
}
vector<vector<string>> partition(string s) {
backtracking(s,0);
return res;
}
};
因子的组合
class Solution {
public:
vector<int>nums;
vector<vector<int>>res;
vector<int>path;
void backtracking(int n,int startIndex){
if(n==1){
if(path.size()>0){
res.push_back(path);
}
return;
}
if(n==0){
return;
}
unordered_set<int>set;
for(int i=startIndex;i<nums.size();++i){
if(n%nums[i]!=0||set.find(nums[i])!=set.end())continue;
set.insert(nums[i]);
path.push_back(nums[i]);
backtracking(n/nums[i],i);
path.pop_back();
}
}
vector<vector<int>> getFactors(int n) {
process(n);
if(nums.size()==0)return res;
backtracking(n,0);
return res;
}
void process(int n){//获取n的所有因子
for(int i=2;i<=sqrt(n);++i){
if(n%i==0){
nums.push_back(i);
nums.push_back(n/i);
}
}
if(nums.size()==0)return;
sort(nums.begin(),nums.end());
}
};
组合总和 III
class Solution {
public:
vector<vector<int>>res;
vector<int>path;
void backtracking(int n,int k,int sum,unordered_set<int>set){
if(path.size()==k){
if(sum==n){
res.push_back(path);
}
return;
}
if(sum>=n){
return;
}
for(int i=1;i<=9;++i){
if(set.find(i)==set.end()){
set.insert(i);
path.push_back(i);
backtracking(n,k,sum+i,set);
path.pop_back();
}
}
}
vector<vector<int>> combinationSum3(int k, int n) {
unordered_set<int>set;
backtracking(n,k,0,set);
return res;
}
};
目标和
class Solution {
public:
int res;
int path;//保存当前路径的和
void backtracking(vector<int>& nums,int curIndex,int target){
if(curIndex>=nums.size()){
if(path==target){
++res;
}
return;
}
int x=nums[curIndex];
path+=x;
backtracking(nums,curIndex+1,target);
path-=x;
path-=x;
backtracking(nums,curIndex+1,target);
path+=x;
}
int findTargetSumWays(vector<int>& nums, int target) {
res=0;
path=0;
backtracking(nums,0,target);
return res;
}
};
所有可能的路径
class Solution {
public:
vector<vector<int>> res;
vector<int>path;
void backtracking(vector<vector<int>>& graph,int n,int curIndex){
path.push_back(curIndex);
if(curIndex==n-1){
res.push_back(path);
return;
}
vector<int> g=graph[curIndex];
for(int i:g){
backtracking(graph,n,i);
path.pop_back();
}
}
vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& graph) {
backtracking(graph,graph.size(),0);
return res;
}
};
路径总和 II
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>>res;
vector<int>path;
void backtracking(TreeNode* cur,int rest){
path.push_back(cur->val);
if(cur->left==nullptr&&cur->right==nullptr&&rest==cur->val){
res.push_back(path);
return;
}
if(rest!=cur->val&&cur->left==nullptr&&cur->right==nullptr){
return;
}
if(cur->left!=nullptr){
backtracking(cur->left,rest-cur->val);
path.pop_back();
}
if(cur->right!=nullptr){
backtracking(cur->right,rest-cur->val);
path.pop_back();
}
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
if(root==nullptr)return res;
backtracking(root,targetSum);
return res;
}
};
单词搜索
class Solution {
public:
vector<vector<bool>>vis;
bool res;
int dx[4];
int dy[4];
void backtracking(vector<vector<char>>& board,int row,int col,string word,int curIndex){
int r=board.size();
int c=board[0].size();
if(curIndex==word.length()){
res=true;
return;
}
if(row<0||col<0||row>=r||col>=c){
return ;
}
if(res){
return;
}
if(vis[row][col]||word[curIndex]!=board[row][col])return;
vis[row][col]=true;
for(int i=0;i<4;++i){
int rn=row+dx[i];
int cn=col+dy[i];
backtracking(board,rn,cn,word,curIndex+1);
}
vis[row][col]=false;
}
bool exist(vector<vector<char>>& board, string word) {
vis.resize(board.size());
for(int i=0;i<board.size();++i){
vis[i].resize(board[i].size());
}
res=false;
dx[0]=-1;dx[1]=1;dx[2]=0;dx[3]=0;
dy[0]=0;dy[1]=0;dy[2]=-1;dy[3]=1;
for(int i=0;i<board.size();++i){// 遍历开始位置(i,j)
for(int j=0;j<board[0].size();++j){
vector<vector<bool>>v;
v.resize(board.size());
for(int i=0;i<board.size();++i){
v[i].resize(board[i].size());
}
vis=v;
backtracking(board,i,j,word,0);
if(res)return true;
}
}
return false;
}
};
组合总和 II
class Solution {
public:
vector<vector<int>>res;
vector<int>path;
void backtracking(vector<int>& candidates,int rest,int startIndex){
if(rest==0){
res.push_back(path);
return;
}
if(rest<0)return;
unordered_set<int>set;
for(int i=startIndex;i<candidates.size();++i){
if(rest>=candidates[i]&&set.find(candidates[i])==set.end()){
path.push_back(candidates[i]);
set.insert(candidates[i]);
backtracking(candidates,rest-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);
return res;
}
};
组合总和
class Solution {
public:
vector<vector<int>>res;
vector<int>path;
void backtracking(vector<int>& candidates,int rest,int startIndex){
if(rest==0){
res.push_back(path);
return;
}
if(rest<0)return;
for(int i=startIndex;i<candidates.size();++i){
if(candidates[i]<=rest){
path.push_back(candidates[i]);
backtracking(candidates,rest-candidates[i],i);
path.pop_back();
}
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
// sort(candidates.begin(),candidates.end());
backtracking(candidates,target,0);
return res;
}
};
括号生成
class Solution {
public:
vector<string>res;
string path;
void backtracking(int n,int left,int right){
if(path.length()==2*n){
res.push_back(path);
return;
}
if(left<right||left>n||right>n)return;//无效的括号序列
if(left<n&&right<n){
path+='(';
backtracking(n,left+1,right);
path=path.substr(0,path.length()-1);
path+=')';
backtracking(n,left,right+1);
path=path.substr(0,path.length()-1);
}else if(right<n){
path+=')';
backtracking(n,left,right+1);
path=path.substr(0,path.length()-1);
}
}
vector<string> generateParenthesis(int n) {
backtracking(n,0,0);
return res;
}
};
电话号码的字母组合
class Solution {
public:
vector<vector<char>>letter;
// bool vis[10][4];
vector<string>res;
string path;
void backtracking(string digits,int curIndex){
if(path.length()==digits.length()){
res.push_back(path);
return;
}
vector<char>l=letter[digits[curIndex]-'0'];
for(char ch:l){
path+=ch;
backtracking(digits,curIndex+1);
path=path.substr(0,path.length()-1);
}
}
vector<string> letterCombinations(string digits) {
if(digits=="")return res;
letter.resize(10);
letter[2]={'a','b','c'};
letter[3]={'d','e','f'};
letter[4]={'g','h','i'};
letter[5]={'j','k','l'};
letter[6]={'m','n','o'};
letter[7]={'p','q','r','s'};
letter[8]={'t','u','v'};
letter[9]={'w','x','y','z'};
backtracking(digits,0);
return res;
}
};
全排列 II
class Solution {
public:
vector<vector<int>>res;
vector<int>path;
vector<bool>vis;
void backtracking(vector<int>& nums){
if(nums.size()==path.size()){
res.push_back(path);
return;
}
unordered_set<int>set;
for(int i=0;i<nums.size();++i){//遍历当前层的可选元素
if(!vis[i]&&set.find(nums[i])==set.end()){//不仅要求当前元素是未被访问过的,还要求之前没重复出现
set.insert(nums[i]);
path.push_back(nums[i]);
vis[i]=true;
backtracking(nums);
path.pop_back();
vis[i]=false;
}
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
vis.resize(nums.size());
backtracking(nums);
return res;
}
};
全排列
class Solution {
public:
vector<vector<int>>res;
vector<int>path;
void backtracking(vector<int>& nums,unordered_set<int>set){
if(nums.size()==path.size()){
res.push_back(path);
return;
}
unordered_set<int>uset(set);
for(int n:nums){
if(uset.find(n)==uset.end()){
uset.insert(n);
path.push_back(n);
backtracking(nums,uset);
path.pop_back();
uset.erase(n);
}
}
}
vector<vector<int>> permute(vector<int>& nums) {
unordered_set<int>set;
backtracking(nums,set);
return res;
}
};
子集 II
class Solution {
public:
vector<vector<int>>res;
vector<int>path;
void backtracking(vector<int>& nums,int startIndex){
res.push_back(path);
if(startIndex==nums.size()){
return;
}
unordered_set<int>set;
for(int i=startIndex;i<nums.size();++i){
if(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>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(),nums.end());//去重需要先排序
backtracking(nums,0);
return res;
}
};
子集
class Solution {
public:
vector<vector<int>>res;
vector<int>path;
void backtracking(vector<int>& nums,int startIndex){
res.push_back(path);//沿途的路径都要收集
if(startIndex==nums.size()){
return;
}
for(int i=startIndex;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 res;
}
};
组合
class Solution {
public:
vector<vector<int>>res;
vector<int>path;
void backtracking(int n,int k,int startIndex){
if(path.size()==k){
res.push_back(path);
return;
}
for(int i=startIndex;i<=n;++i){
path.push_back(i);
backtracking(n,k,i+1);
path.pop_back();//回溯
}
}
vector<vector<int>> combine(int n, int k) {
backtracking(n,k,1);
return res;
}
};