【2023/04/21-04/28】回溯算法

学习链接:

1.分割回文串

题目来源:131.分割回文串

题解:

class Solution {
public:
    vector<vector<int>> f;
    vector<vector<string>> ret;
    vector<string> ans;
    int n;
    vector<vector<string>> partition(string s) {
        n=s.size();
        f=vector<vector<int>>(n,vector<int>(n,true));
        for(int i=n-1;i>=0;i--){
            for(int j=i+1;j<n;j++){
                f[i][j]=f[i+1][j-1]&&(s[i]==s[j]);
            }
        }
        dfs(s,0);
        return ret;
    }
    void dfs(string s,int i){
        if(i==n){
            ret.push_back(ans);
            return;
        }
        for(int j=i;j<n;j++)
        {
            if(f[i][j]){
                ans.push_back(s.substr(i,j-i+1));
                dfs(s,j+1);
                ans.pop_back();
            }
        }
    }
};

2.组合总数

题目来源:39.组合总数
题解:

class Solution {
public:
    vector<vector<int>> ret;
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<int> ans;
        int n=candidates.size();
        sort(candidates.begin(),candidates.end());
        backtrack(candidates,0,n,ans,target);
        return ret;
    }
    void backtrack(vector<int>& candidates,int begin,int len,vector<int>& ans, int target){
        if(target==0)
        {
            ret.push_back(ans);
            return;
        }
        for(int i=begin;i<len;i++){
            if(target-candidates[i]<0)
                return;
            ans.push_back(candidates[i]);
            backtrack(candidates,i,len,ans,target-candidates[i]);
            ans.pop_back();
        }
    }
};

3.划分为k个相等的子集

题目来源:
698. 划分为k个相等的子集
题解:

class Solution {
public:
    bool canPartitionKSubsets(vector<int>& nums, int k) {
        int n=nums.size(),sum=0;
        for(int i=0;i<n;i++)
            sum+=nums[i];
        if(sum%k!=0)
            return false;
        sum/=k;
        vector<int> bucket(k);
        sort(nums.begin(),nums.end(),greater<int>());//按降序排序后,效率更好!!!
        return backtrack(nums,0,bucket,k,sum);
    }
    bool backtrack(vector<int>& nums,int index,vector<int>& bucket,int k,int sum){
        if(index==nums.size()){
            return true;
        }
        for(int i=0;i<k;i++){
            if(i>0&&bucket[i]==bucket[i-1]) continue;//去掉重复计算的情况!!能够优化效率!!
            if(bucket[i]+nums[index]>sum) continue;
            bucket[i]+=nums[index];
            if(backtrack(nums,index+1,bucket,k,sum))    return true;
            bucket[i]-=nums[index];
        }
        return false;
    }
};

4.子集

题目来源:78.子集
题解:

class Solution {
public:
    vector<vector<int>> res;
    vector<vector<int>> subsets(vector<int>& nums) {
        int n=nums.size();
        if(n==0) return res;
        vector<int> ans;
        backtrack(nums,ans,0);
        return res; 
    }
    void backtrack(vector<int>& nums,vector<int>& ans,int index){
        if(index==nums.size()){
            res.push_back(ans);
            return;
        }
        ans.push_back(nums[index]);
        backtrack(nums,ans,index+1);
        ans.pop_back();
        backtrack(nums,ans,index+1);
    }
};

5.单词拆分II*******

题目来源:140.单词拆分II
题解:

//回溯法
class Solution {
public:
    unordered_set<string> wordset;
    vector<string> ans;
    vector<string> wordBreak(string s, vector<string>& wordDict) {
        for(auto word:wordDict)
            wordset.insert(word);
        string str="";
        backtrack(s,wordset,0,str);
        return ans;
    }
    void backtrack(string s,unordered_set<string>& st,int idx,string track){
        int n=s.size();
        if(idx==n){
            ans.push_back(track);
            return;
        }
        for(int i=idx;i<n;i++){
            string word=s.substr(idx,i-idx+1);
            if(st.find(word)!=st.end()){
                int pos=track.size();
                if(pos>0)
                    track+=" ";
                track+=word;
                backtrack(s,st,i+1,track);
                track.erase(track.begin()+pos,track.end());
            }
        }
    }
};

//动态规划
class Solution {
private:
    unordered_map<int, vector<string>> ans;
    unordered_set<string> wordSet;

public:
    vector<string> wordBreak(string s, vector<string>& wordDict) {
        //wordSet = unordered_set(wordDict.begin(), wordDict.end());
        for(auto word:wordDict)
            wordSet.insert(word);
        backtrack(s, 0);
        return ans[0];
    }

    void backtrack(const string& s, int index) {
        if (!ans.count(index)) {
            if (index == s.size()) {
                ans[index] = {""};
                return;
            }
            ans[index] = {};
            for (int i = index + 1; i <= s.size(); ++i) {
                string word = s.substr(index, i - index);
                if (wordSet.count(word)) {
                    backtrack(s, i);
                    for (const string& succ: ans[i]) {
                        ans[index].push_back(succ.empty() ? word : word + " " + succ);
                    }
                }
            }
        }
    }
};

6.复原IP地址

题目来源:93. 复原 IP 地址
题解:

class Solution {
public:
    vector<string> ans;
    vector<int> segment;
    vector<string> restoreIpAddresses(string s) {
        segment.resize(4);
        backtrack(s,0,0);
        return ans;
    }
    void backtrack(string s,int segidx,int segstart){
        if(segidx==4){
            if(segstart==s.size()){
                string addr;
                for(int i=0;i<3;i++){
                    addr+=to_string(segment[i]);
                    addr+=".";
                }
                addr+=to_string(segment[3]);
                ans.push_back(addr);
            }
            return;
        }
        if(segstart==s.size())
            return;
        if(s[segstart]=='0'){
            segment[segidx]=0;
            backtrack(s,segidx+1,segstart+1);
        }
        int addr=0;
        for(int i=segstart;i<s.size();i++){
            addr=addr*10+(s[i]-'0');
            if(addr>0&&addr<=255){
                segment[segidx]=addr;
                backtrack(s,segidx+1,i+1);
            }
            else
                break;
        }
    }
};

7.递增子序列

题目来源:491. 递增子序列
题解:

class Solution {
public:
    vector<int> temp; 
    vector<vector<int>> ans;

    void dfs(int cur, int last, vector<int>& nums) {
        if (cur == nums.size()) {
            if (temp.size() >= 2) {
                ans.push_back(temp);
            }
            return;
        }
        if (nums[cur] >= last) {
            temp.push_back(nums[cur]);
            dfs(cur + 1, nums[cur], nums);
            temp.pop_back();
        }
        if (nums[cur] != last) {
            dfs(cur + 1, last, nums);
        }
    }

    vector<vector<int>> findSubsequences(vector<int>& nums) {
        dfs(0, INT_MIN, nums);
        return ans;
    }
};

8. 机器人的运动范围

题目来源:剑指 Offer 13. 机器人的运动范围
题解:

class Solution {
public:
    int get(int x){
        int res=0;
        while(x){
            res=res+(x%10);
            x/=10;
        }
        return res;
    }
    int movingCount(int m, int n, int k) {
        if(k==0) return 1;
        vector<vector<int>> vis(m,vector<int>(n,0));
        int ans=1;
        vis[0][0]=1;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if((i==0&&j==0)||get(i)+get(j)>k) continue;
                if (i - 1 >= 0) vis[i][j] |= vis[i - 1][j];
                if (j - 1 >= 0) vis[i][j] |= vis[i][j - 1];
                ans += vis[i][j];
            }
        }
        return ans;
    }
};

//解法2
class Solution {
public:
    int get(int x){
        int res=0;
        while(x){
            res=res+(x%10);
            x/=10;
        }
        return res;
    }
    int movingCount(int m, int n, int k) {
        if(k==0) return 1;
        queue<pair<int,int>> q;
        vector<vector<int>> vis(m,vector<int>(n,0));
        int dx[2] = {0, 1};
        int dy[2] = {1, 0};
        q.push({0,0});
        vis[0][0]=1;
        int ans=1;
        while(!q.empty()){
            auto [x,y]=q.front();
            q.pop();
            for (int i = 0; i < 2; ++i) {
                int tx = dx[i] + x;
                int ty = dy[i] + y;
                if (tx < 0 || tx >= m || ty < 0 || ty >= n || vis[tx][ty] || get(tx) + get(ty) > k) continue;
                q.push(make_pair(tx, ty));
                vis[tx][ty] = 1;
                ans++;
            }
        }
        return ans;
    }
};

9.单词搜索*****

题目来源:79.单词搜索

class Solution {
public:
    int m,n;
    bool exist(vector<vector<char>>& board, string word) {
        m=board.size(),n=board[0].size();
        vector<vector<bool>> used(m,vector<bool>(n,false));
        int len=word.size();
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(dfs(board,m,n,used,i,j,word,len,0))
                    return true;
            }
        }
        return false;
    }
    int directions[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
    bool dfs(vector<vector<char>>& board,int m,int n,vector<vector<bool>>& used,int i,int j,string& word,int len,int idx){
        if(board[i][j]!=word[idx])
            return false;
        else if(idx==len-1)
            return true;
        used[i][j]=true;
        bool result=false;
        for (int sel = 0; sel < 4; sel++) {
        int newi = i + directions[sel][0], newj = j + directions[sel][1];
        if (newi >= 0 && newi < m && newj >= 0 && newj < n) {
            if (!used[newi][newj]) {
                bool flag = dfs(board,m,n,used,newi,newj,word,len, idx+1);
                if (flag) {
                    result = true;
                    break;
                }
            }
        }
    }
    used[i][j] = false;
    return result;
    }
};

10.打开转盘锁

题目来源:752.打开转盘锁
剑指 Offer II 109. 开密码锁
题解:

class Solution {
public:
    string plusone(string s,int j){
        if(s[j]=='9')
            s[j]='0';
        else 
            s[j]+=1;
        return s;
    }
    string minusone(string s,int j){
        if(s[j]=='0')
            s[j]='9';
        else 
            s[j]-=1;
        return s;
    }
    int openLock(vector<string>& deadends, string target) {
        unordered_set<string> deads;
        for(auto& s:deadends){
            deads.insert(s);
        }
        unordered_set<string> vis;
        queue<string> q;
        int step=0;
        q.push("0000");
        vis.insert("0000");
        while(!q.empty()){
            int sz=q.size();
            for(int i=0;i<sz;i++){
                string cur=q.front();
                q.pop();
                if(deads.count(cur))
                    continue;
                if(cur==target)
                    return step;
                for(int j=0;j<4;j++){
                    string up=plusone(cur,j);
                    if(!vis.count(up)){
                        q.push(up);
                        vis.insert(up);
                    }
                    string down=minusone(cur,j);
                    if(!vis.count(down)){
                        q.push(down);
                        vis.insert(down);
                    }
                }
            }
            step++;
        }
        return -1;
    }
};

//双向BFS
class Solution {
public:
    string plusone(string s,int j){
        if(s[j]=='9')
            s[j]='0';
        else
            s[j]+=1;
        return s;
    }
    string minusone(string s,int j){
        if(s[j]=='0')
            s[j]='9';
        else
            s[j]-=1;
        return s;
    }
    int openLock(vector<string>& deadends, string target) {
        unordered_set<string> deads(deadends.begin(),deadends.end());
        unordered_set<string> q1,q2,vis;
        int step=0;
        q1.insert("0000");
        q2.insert(target);
        while(!q1.empty()&&!q2.empty()){
            unordered_set<string> temp;
            for(auto cur:q1){
                if(deads.count(cur))
                    continue;
                if(q2.count(cur))
                    return step;
                vis.insert(cur);
                for(int j=0;j<4;j++){
                    string up=plusone(cur,j);
                    if(!vis.count(up))
                        temp.insert(up);
                    string down=minusone(cur,j);
                    if(!vis.count(down))
                        temp.insert(down);
                }
            }
            step++;
            q1=q2;
            q2=temp;
        }
        return -1;
    }
};

11.二进制矩阵中的最短路径

题目来源:1091. 二进制矩阵中的最短路径
题解:

class Solution {
public:
    int dir[8][2]={{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,0},{1,-1},{1,1}};
    int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
        int n=grid.size();
        int m=grid[0].size();
        
        if(grid[0][0]!=0) return -1;
        if(grid[n-1][m-1]==1) return -1;
        if(n==1) return 1;

        queue<pair<int,int>> q;
        q.push({0,0});
        grid[0][0]=1;
        int ans=1;
        while(!q.empty()){
            
            int k=q.size();
            for(int r=0;r<k;r++){
                pair<int,int> p=q.front();
                q.pop();
                int x=p.first;
                int y=p.second;
                for(int i=0;i<8;i++){
                    int xx=x+dir[i][0];
                    int yy=y+dir[i][1];
                    if(xx==n-1&&yy==m-1){
                            return ans+1;
                        }
                    if(xx>=0&&yy>=0&&xx<n&&yy<m){
                        if(grid[xx][yy]==0){
                            q.push({xx,yy});
                            grid[xx][yy]=1;
                        }
                    }
                }
            }
            ans+=1;
        } 
        return -1;
    }
};

12.二叉树中所有距离为 K 的结点

题目来源:863. 二叉树中所有距离为 K 的结点
题解:


/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    vector<int> g[510];
    vector<int> ans;
public:
    void BFS(TreeNode *root)
    {
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty())
        {
            auto head=q.front();
            q.pop();
            if(head->left)
            {
                q.push(head->left);
                g[head->val].push_back(head->left->val);
                g[head->left->val].push_back(head->val);
            }
            if(head->right)
            {
                q.push(head->right);
                g[head->val].push_back(head->right->val);
                g[head->right->val].push_back(head->val);
            }
        }
    }
    void DFS(vector<bool>& vis,int root,int k,int step)
    {
        vis[root]=true;
        if(step==k)
        {
            ans.push_back(root);
            return;
        }
        for(int i=0;i<g[root].size();i++)
        {
            if(!vis[g[root][i]]) DFS(vis,g[root][i],k,step+1);
        }
    }
    vector<int> distanceK(TreeNode* root, TreeNode* target, int k) {
        vector<bool> vis(510,false);
        BFS(root);
        DFS(vis,target->val,k,0);
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值