17. 电话号码的字母组合/回溯/队列【leetcode】

17. 电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
在这里插入图片描述
示例 1:
输入:digits = “23”
输出:[“ad”,“ae”,“af”,“bd”,“be”,“bf”,“cd”,“ce”,“cf”]

示例 2:
输入:digits = “”
输出:[]

示例 3:
输入:digits = “2”
输出:[“a”,“b”,“c”]

提示:
0 <= digits.length <= 4
digits[i] 是范围 [‘2’, ‘9’] 的一个数字。

队列

该方法较好理解
如例子“23”
先将2对应的a,b,c加入队列,然后每次将a pop出队列时,将a分别与3对应的def分别组合加入队列。

代码如下:

class Solution {
public:
    vector<string> letterCombinations(string digits) 
    {
        vector<string>res;
        string s[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
        queue<string>q;
        int n=digits.size();
        for(int i=0;i<n;i++)
        {
            if(q.empty())
            {
                for(int j=0;j<s[digits[i]-'0'].size();j++)
                q.push(s[digits[i]-'0'].substr(j,1));
            }
            else
            {
                while(q.front().size()<i+1)
                {
                    for(int j=0;j<s[digits[i]-'0'].size();j++)
                    {
                        string e=q.front()+s[digits[i]-'0'].substr(j,1);
                        q.push(e);
                    }
                    q.pop();
                }
            }
        }
        while(!q.empty())
        {
            res.push_back(q.front());
            q.pop();
        }
        return res;
    }
};

回溯

这个方法可能较为难理解
回溯其实可以理解为多条路分别走,你选择进入函数即走下一步,不进入函数往下走就是换个方向走,还没到下一步。
这里讲一讲回朔法的思路:1这一步要干嘛,2下一步要干嘛,3目的是什么
使用回溯法最好要能画成n叉树的结构,树的宽度就用for循环,深度就用递归。
另外回溯法要注意进入下一层递归时某些值才改变,可以在调用自身的括号中改变,不能在调用前面改变
如果不能在括号中改变,可以这样

for(int i=idx;i<candidates.size();i++)
        {
            if(candidates[i]>target-sum) continue;
            if(candidates[i]<=target-sum)
            {
                v.push_back(candidates[i]);
                function(target,sum+candidates[i],candidates,v,i);
                v.pop_back();
            }
        }

push之后再pop这样就不会对后面for循环操作造成影响

另外,在同一层的回溯数据是不变的,但是二维数组传进去就可以积累答案,因为后面对一维数组有回溯操作,所以保证数据不变,而对结果数组没有,所以结果数组可以积累。
注意如果要可以积累的话,要传入地址!!!!!!!!!
int也是,如果传入的是固定的值,就可以不用传入地址。
然后这一题配一张图更好理解
在这里插入图片描述
首先第一步是把第一个数字的字符加进去,第二步是把第二个数字的字符加进去,目的是将字符相加并放入数组中
故可以用函数加字符,同时这里每一个数字都要回溯,故还有用for循环

class Solution {
public:
    string s[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
    vector<string>res;
    void v(string digits,string ss,int idx)
    {
       if(idx==digits.size()) res.push_back(ss);
       else
       {
           string x=s[digits[idx]-'0'];
           for(int i=0;i<x.size();i++)
               v(digits,ss+x[i],idx+1);
               //在同一递归层下idx是不变的
       }
    }
    vector<string> letterCombinations(string digits) 
    {
        if(digits.size()==0) return res;
        v(digits,"",0);
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值