【算法分析与设计】电话号码的字母组合

       📝个人主页:五敷有你      

 🔥系列专栏:算法分析与设计

⛺️稳中求进,晒太阳

题目

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

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

示例

示例 1:

输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例 2:

输入:digits = ""
输出:[]

示例 3:

输入:digits = "2"
输出:["a","b","c"]

思路(回溯)

回溯是一种通过不断尝试所有可能的解决方案来解决问题的算法。它的基本思路是逐步构建解决方案,当发现当前方案不可行时,进行回溯(撤销上一步的选择),并尝试其他的选择,直到找到问题的解决方案或者确定不存在解决方案为止。以下是回溯算法的一般套路:

明确问题的决策树结构: 将问题转化为一个决策树,每个节点代表一个决策点,通过递归的方式遍历这棵决策树,尝试所有可能的选择。

编写递归函数: 设计一个递归函数来遍历决策树。函数的参数通常包括当前状态、已经做出的选择等。

确定终止条件: 在递归函数中,明确何时可以终止递归,一般是当达到问题的边界条件时,如处理到最后一个数字时。

对每个决策点进行选择与撤销选择: 在递归函数中,对当前决策点做出一个选择,并根据这个选择递归地处理下一个决策点;在处理完当前决策点后,需要撤销这个选择,以便尝试其他选择。

处理剪枝: 如果问题中存在一些无效的分支,可以通过剪枝来减少搜索空间,提高效率。剪枝的条件可以根据具体问题而定。

处理解的存储与处理: 在找到一个解时,根据具体需求进行解的存储或处理。可能需要将解存储起来,或者直接在递归函数中进行处理。

清理状态: 在回溯的过程中,需要及时清理状态,以便下一次搜索。这包括清理选择,恢复状态等。

回溯算法的实现通常比较灵活,因为它适用于各种问题,包括组合问题、排列问题、子集问题等。在具体解决问题时,需要根据问题的特点来设计具体的回溯算法。

算法设计与分析

  1. 首先,创建一个映射表,将数字与字母的对应关系存储起来。可以使用HashMap来实现这个映射。

  2. 然后,使用回溯算法进行递归。递归函数应该接受三个参数:当前正在处理的数字字符串、当前索引、当前正在生成的组合字符串。

  3. 在递归函数中,首先检查当前索引是否越界,如果越界,则将当前生成的组合字符串加入结果列表中,并返回。

  4. 如果当前索引没有越界,取出当前索引对应的数字,并获取其对应的字母列表。

  5. 遍历这个字母列表,每次取出一个字母,将其加入当前生成的组合字符串中,并调用递归函数处理下一个数字。

  6. 处理完当前数字后,需要回溯到上一状态,将刚才加入的字母从组合字符串中移除,继续遍历其他字母。

  7. 当所有数字处理完毕后,递归函数结束。

  8. 最后,返回结果列表即可

代码实现

class Solution {
    public List<String> letterCombinations(String digits) {
        List<String> combinations = new ArrayList<String>();
        if (digits.length() == 0) {
            return combinations;
        }
        Map<Character, String> phoneMap = new HashMap<Character, String>() {{
            put('2', "abc");
            put('3', "def");
            put('4', "ghi");
            put('5', "jkl");
            put('6', "mno");
            put('7', "pqrs");
            put('8', "tuv");
            put('9', "wxyz");
        }};
        backtrack(combinations, phoneMap, digits, 0, new StringBuffer());
        return combinations;
    }

    public void backtrack(List<String> combinations, Map<Character, String> phoneMap, String digits, int index, StringBuffer combination) {
        if (index == digits.length()) {
            combinations.add(combination.toString());
        } else {
            char digit = digits.charAt(index);
            String letters = phoneMap.get(digit);
            int lettersCount = letters.length();
            for (int i = 0; i < lettersCount; i++) {
                combination.append(letters.charAt(i));
                backtrack(combinations, phoneMap, digits, index + 1, combination);
                combination.deleteCharAt(index);
            }
        }
    }
}

运行结果

  • 21
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

五敷有你

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

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

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

打赏作者

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

抵扣说明:

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

余额充值