17. Letter Combinations of a Phone Number (Medium)——电话号码的字母组合

本文介绍了一种使用回溯算法解决电话号码字母组合问题的方法。通过深度优先搜索(DFS)的回溯技术,实现了从数字到其对应字母的所有可能组合的生成。文章详细解释了回溯算法的工作原理,并提供了一个清晰的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

这是一道回溯算法的典型例题。

 

题目: 

 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

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

示例:

输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。

 

解题算法:

 

Backtracking

Backtracking(回溯)属于 DFS。

  • 普通 DFS 主要用在 可达性问题 ,这种问题只需要执行到特点的位置然后返回即可。
  • 而 Backtracking 主要用于求解 排列组合 问题,例如有 { 'a','b','c' } 三个字符,求解所有由这三个字符排列得到的字符串,这种问题在执行到特定的位置返回之后还会继续执行求解过程。

因为 Backtracking 不是立即返回,而要继续求解,因此在程序实现时,需要注意对元素的标记问题:

  • 在访问一个新元素进入新的递归调用时,需要将新元素标记为已经访问,这样才能在继续递归调用时不用重复访问该元素;
  • 但是在递归返回时,需要将元素标记为未访问,因为只需要保证在一个递归链中不同时访问一个元素,可以访问已经访问过但是不在当前递归链中的元素。

 

思路:

 大致与DFS深度优先遍历一致。功能靠findCombinations方法实现,其中prefix参数是上一次拼接好的字符串,如果它长度符合要求了,说明已经拼好,在结果中添加该字符串并返回即可,如果长度没有达到要求,如传入的数字是23,prefix=“a”,说明还没有拼好,把KEY[a.length]字符串中的三个字母遍历一遍,每次让prefix添加一个字母,然后对其递归调用本方法。比如经过

prefix.append(c);

操作之后,prefix为“ad”,再调用

findCombinations(result, prefix, digits);

传入的prefix长度为2,已经满足要求了,此时本次递归return,倒退到上一层递归的for循环里,此时我们的prefix还是“ad”,如果没有让prefix-1,那么当进入第二次for循环时,prefix.append(c)执行后,prefix就变成了“ade”,这就gg了,所以要递归之后还要让prefix-1,不能使其只增不减。

 

代码:

public class LetterCombinationsOfAPhoneNumber {
    private static final String[] KEYS = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

    public List<String> letterCombinations(String digits) {
        if (null == digits || digits.length()==0) return new ArrayList<>();

        List<String> result = new ArrayList<>();
        findCombinations(result, new StringBuilder(), digits);
        return result;
    }

    private void findCombinations(List<String> result, StringBuilder prefix, String digits) {
        if (prefix.length() >= digits.length()) {
            result.add(prefix.toString());
            return;
        }
        int curNum = digits.charAt(prefix.length())-'0';
        for (char c : KEYS[curNum].toCharArray()) {
            prefix.append(c);
            findCombinations(result, prefix, digits);
            prefix.deleteCharAt(prefix.length()-1);
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

请保持优秀。

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

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

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

打赏作者

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

抵扣说明:

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

余额充值