[算法题解详细]回溯法解力扣17电话号码的字母组合

提示:

  1. 0 <= digits.length <= 4

  2. digits[i] 是范围 [‘2’, ‘9’] 的一个数字。

思路


看到这个题目的第一感觉就是会觉得很麻烦,题目给出digits数组是一个仅包含2-9数字的字符串,同时2-9数字又代表了电话按键上相应的几个字符串,这里我们可以开一个string数组letter用来保存2-9数字代表的分别是哪些字符串,同时为了防止下标不对应,我们需要给0,1下标给上一个空字符串或者是随便一个字符,因为我们使用的下标也只有2-9,并不会使用到0,1下标,但是以防万一我们还是给上空字符串要好一些。

然后我们看示例会发现digits数组中有几个数字,那么答案就是这几个数字代表的那几个字符串每个字符串取一个字符得出的排列,顺序就是按digits数组给出的数字顺序来,这时候会有人疑惑,digits数组给出的字符串长度是变化的,也就是数字个数从0-8都可能会有,如果是两个数字两层循环就够了,八个数字就要八层循环,

那么如何来动态改变循环层数呢?

这里就是dfs的使用了,同时也是递归,我们通过给dfs函数传参,然后通过参数来动态控制循环层数,达到题目指定的层数,也就是digits数组的长度就直接终止递归,这样就实现了动态控制循环层数了。

然后是字符的组合,就需要我们用到回溯法了,接下来我们看代码

代码


首先在主函数中,我们要初始化ans容器,用来存储答案,并且要定义好letter数组,用来保存下标2-9对应的字符串

还要定义一个temp字符串,用来保存每一个字符串组合

注意这里我们要对digits数组判空,如果是空的我们需要直接返回初始化的ans容器

class Solution {

public:

int n;

string letter[10] = {“”, “”, “abc”, “def”, “ghi”, “jkl”, “mno”, “pqrs”, “tuv”, “wxyz”};

vector ans;

string temp;

vector letterCombinations(string digits) {

n = digits.length();

ans.clear();

if(digits.length() == 0) {

return ans;

}

dfs(digits, 0);

return ans;

}

};

dfs函数中,出口条件还是当递归层等于了digits数组的长度时,我们将当前temp保存的字符串组合加入ans容器中,因为我们在dfs中设置的条件,会让只要是递归到了这一层的temp就是一定满足答案的字符串组合,加入容器后我们直接终止当前递归,回溯到上一层递归,寻找其他可行的字符串组合

void dfs(string& digits, int u) {

if(u == n) {

ans.push_back(temp);

return;

}

}

在这里我们要注意digits数组是一个字符串,所以我们取每一位字符的时候需要转为数字才能直接使用为下标,将字符转为数字的方法有很多,我这里是直接**-'0’字符转成数字**,然后在每一次递归中我们都要循环一遍当前的letter下标为digits[u]数字的字符串,来进行组合,这里要注意回溯的应用,就是temp在下一层递归前添加当前选中的字符,在下一层递归完成后,我们需要回到添加字符前的那一步,方便寻找其他的可行的组合

void dfs(string& digits, int u) {

if(u == n) {

ans.push_back(temp);

return;

}

int t = digits[u] - ‘0’;

for(int i = 0; i < letter[t].length(); i++) {

if(u + 1 > n) {

return;

}

temp += letter[t][i];

dfs(digits, u + 1);

temp = temp.substr(0, temp.length() - 1);

}

}

这里加了一个u+1是防止越界的,同时也相当于一个剪枝

下面是完整代码:

class Solution {

public:

int n;

string letter[10] = {“”, “”, “abc”, “def”, “ghi”, “jkl”, “mno”, “pqrs”, “tuv”, “wxyz”};

vector ans;

string temp;

void dfs(string& digits, int u) {

if(u == n) {

ans.push_back(temp);

return;

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
ndroid开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!**

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值