递归与回溯12:电话号码问题
Posted 纵横千里,捭阖四方
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了递归与回溯12:电话号码问题相关的知识,希望对你有一定的参考价值。
LeetCode17,电话号码组合问题,也是热度非常高的一个题目,给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
我们说回溯仍然会存在暴力枚举的情况,这个题就很典型,例如如果输入23,那么,2就有 a、b、c三种情况,3有d、e、f三种情况。所以组合一下就一共就有3*3=9种。如果是233,那么就是27种。从实现的角度来说,两个数字就是两层循环,三个数字就是3层循环。这样是很好理解的,但是如果随便输入一个数字,你该怎么写有几层循环呢?很显然就不能再暴力搜索了,这个与组合问题几乎一样。
进入正题之前,先看一个小问题,这里的9对应4个字母,而1则没有。那该怎么建立字母和数字之间的映射呢?简单,用一个数组就行了,不要写一堆的if else判断。
String[] numString = "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz";
接下来我们就用回溯来解决n层循环的问题,输入23对应的树就是这样的:
树的深度就是输入的数字个数,这里是23,树的深度就是2。而所有的叶子节点就是我们需要的结果["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]。所以这里的终止条件就是,如果当前执行的index 等于输入的数字个数(digits.size)了。注意这里的index是从2开始的,与前面的startIndex不同。
而这里的index也恰好就是上面数组的索引,所以取index指向的数字,并找到对应的字符集,使用for循环来枚举出来,然后循环体内就是回溯过程了。基本实现过程如下:
class Solution
List<String> list = new ArrayList<>();
public List<String> letterCombinations(String digits)
if (digits == null || digits.length() == 0)
return list;
//初始对应所有的数字,为了直接对应2-9,新增了两个无效的字符串""
String[] numString = "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz";
backTracking(digits, numString, 0);
return list;
//每次迭代获取一个字符串,所以会设计大量的字符串拼接,所以这里选择更为高效的 StringBuild
StringBuilder temp = new StringBuilder();
//比如digits如果为"23",num 为0,则str表示2对应的 abc
public void backTracking(String digits, String[] numString, int num)
//遍历全部一次记录一次得到的字符串
if (num == digits.length())
list.add(temp.toString());
return;
//str 表示当前num对应的字符串
String str = numString[digits.charAt(num) - '0'];
for (int i = 0; i < str.length(); i++)
temp.append(str.charAt(i));
//c
backTracking(digits, numString, num + 1);
//剔除末尾的继续尝试
temp.deleteCharAt(temp.length() - 1);
以上是关于递归与回溯12:电话号码问题的主要内容,如果未能解决你的问题,请参考以下文章