回溯算法题目


火柴拼正方形

在这里插入图片描述
在这里插入图片描述

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;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值