来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number

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

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。


leetcode 17 - 电话号码的字母组合_C
image.png
示例 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'] 的一个数字。

答案:

class Solution {

    // 数字到号码的映射
    private String[] map = {"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};

    // 路径
    private StringBuilder sb = new StringBuilder();

    // 结果集
    private List<String> res = new ArrayList<>();

    public List<String> letterCombinations(String digits) {
        if(digits == null || digits.length() == 0) return res;
        backtrack(digits,0);
        return res;
    }

    // 回溯函数
    private void backtrack(String digits,int index) {
        if(sb.length() == digits.length()) {
            res.add(sb.toString());
            return;
        }
        String val = map[digits.charAt(index)-'2'];
        for(char ch:val.toCharArray()) {
            sb.append(ch);
            backtrack(digits,index+1);
            sb.deleteCharAt(sb.length()-1);
        }
    }
}

思路:

我们看到这道题首先最简单暴力的方法就是遍历了,但是有个问题就是我们不知道要用几个for,遇到这种不知道几个for能解决的问题,果断就用回溯,也就是回调函数的方式处理

  • 首先我们是需要一个有所有按键字母的一个集合,所以使用了一个数组来表示

  • 然后当输入的字符串为空必然就是不正常的,直接返回即可

  • 进入回溯方法,例如输入 234,那么当然字母三个作为一个组合记录下来,所以下面的代码就是这个意思

if(sb.length() == digits.length()) 
  • index默认为0,也就是从第一个号码的字母取,首先我们的号码从题中可以知道是从2开始的,所以要取得字母数组中的下标,当然就是 index-2,首先digits.charAt(index),当index 为0的时候取的是第一个号码的值,当index为1就是取第二个号码的值,用这个值减去'2'就取得了当前号码对应的字母组合了,这一点如果不懂就不妨随便写一个号码,然后对应着程序走一下就懂了。
String val = map[digits.charAt(index)-'2'];
  • 下面代码就是核心了,遍历字母组合,例如234,首先遍历2对应的字母组合 abc,b.append(ch),把a添加进去之后就要匹配a开头的剩余两个字母了,这个时候进行回调函数,什么时候结束呢,就是长度跟号码长度一致就返回
  for(char ch:val.toCharArray()) {
            sb.append(ch);
            backtrack(digits,index+1);
            sb.deleteCharAt(sb.length()-1);
        }
  • 最后这个就是切换字母,例如 234,字母aeh拿到了,如果要下一个不得先把h给拿掉,然后继续吗?
 sb.deleteCharAt(sb.length()-1);