面试必刷算法TOP101之回溯篇 TOP11

电话号码的字母组合

题目来源:Leetcode
1、问题描述
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

在这里插入图片描述

在这里插入图片描述
2、思路解析
在这里插入图片描述
3、代码实现

class Solution {
public:
    unordered_map<char,string> st={{'2',"abc"},{'3',"def"},{'4',"ghi"},{'5',"jkl"},{'6',"mno"},{'7',"pqrs"},{'8',"tuv"},{'9',"wxyz"}};
    void DFS(string &digits,vector<string> &dict,string s,int idx){
        
        if(digits.size()==idx){
            //到了这里就i是每个键的的字母的随机一个字母就组合在一起了
            dict.push_back(s);

            return;
        }
        //拿到对应建的字符串
        string str=st[digits[idx]];

        /*
        比如“23”
        idx为0先拿到键2对应的字符串先拿该字符串的第一个字符去组合,当是首字符是开始取递归,给idx加以是为了到达键组合的下一个键也就是键3递归也进入递归函数为键3,也拿到键3对应的字符串,开始后边的遍历,s为上一次递归传下来也就是键2字符串的首字母,这和键3的首字母组合进入下一次递归,该字符串的长度达到回溯条件,开始回退,回退到字符串只剩键2的首字母,这时还是键3的递归函数,继续递归,拿到键3的第2个字符,又一次字符串组合,又一次进入下一次递归
        
        
        */
        for(char ch:str){
            //循环字符组合
            DFS(digits,dict,s+ch,idx+1);
        }

    } 
    vector<string> letterCombinations(string digits) {
        vector<string> v;
        if(digits.size()==0){
            return v;
        }
        DFS(digits,v,"",0);
        return v;
    }
};

组合总和

题目来源:Leetcode
1、问题描述
给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个。
在这里插入图片描述
2、思路解析

在这里插入图片描述
3、代码实现

class Solution {
public:
    void DFS(vector<int> & candidates,int target,
    vector<vector<int>>&v,vector<int> &cur,
    int begin,int sum ){
        //
        if(sum>=target){
            //符合条件保持方案
            if(sum==target){
                //分支数据覆盖
                vector<int> newV(cur.begin(),cur.end());
                v.push_back(newV);
            }
            return;
        }
        for(int i=begin;i<candidates.size();i++){
            //先空开始拿到数据,要是不符合条件就回退
            cur.push_back(candidates[i]);
            //开始条件为i是为了防止寻找的组合前边的组合重复
            DFS(candidates,target,v,cur,i,sum+candidates[i]);
            //不符合条件或者已经达到条件开始回退
            cur.erase(cur.end()-1);

        }
    }
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
            vector<vector<int>> v;
            vector<int> vm;
            DFS(candidates,target,v,vm,0,0);
            return v;
    }
};

N皇后问题

题目来源:Leetcode
1、问题描述
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
在这里插入图片描述
2、思路解析

在这里插入图片描述

3、代码实现

class Solution {
public:
    void DFS(vector<vector<pair<int,int>>>&allret,vector<pair<int,int>> &curret,int cur/*当前行*/,int n){
        if(curret.size()>=n){
            //保存当前结果
            allret.push_back(curret);
            return;
        }
        //确定当前行每个位置是不是和已经确认的皇后产生冲突
        for(int i=0;i<n;i++){
            //保证当前皇后不和其他一直皇后位置冲突
            if(isVaild(curret,cur,i)){
                //确定当前皇后位置
                curret.push_back(make_pair(cur,i));
                //确定下一行皇后位置
                DFS(allret,curret,cur+1,n);
                //当前行的和列的位置冲突,尝试其他位置列的
                curret.pop_back();
            }
        }

    }

    bool isVaild(vector<pair<int,int>> &curret,int row/*当前行*/,int col){
    //判断当前位置是不是和已知皇后位置产生冲突
        for(auto o:curret){
            //不符合条件
            //首先排除行数的干扰

            if(col==o.second || o.first-o.second==row-col || o.first + o.second==row+col){
                return false;
            }
        }
       return true;
    }
    vector<vector<string>> isV(vector<vector<pair<int,int>>>&allret,int n){
         vector<vector<string>> curr;
        for(auto o:allret){
         
            vector<string> v(n,string(n,'.'));
            //改皇后位置为Q
            for(auto s:o){
                v[s.first][s.second]='Q';
            }
            curr.push_back(v);
        }
        return curr;
    }
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<pair<int,int>>>allret;
        vector<pair<int,int>> cur;
        DFS(allret,cur,0,n);
        return isV(allret,n);
    }
};
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自首的小偷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值