力扣刷题之17.电话号码的字母组合

文章描述了如何利用递归和回溯算法解决给定数字字符串(如电话按键上的2-9)表示的所有可能字母组合问题。通过预先定义的字母映射和StringBuilder辅助,实现穷举并存储所有合法组合。
摘要由CSDN通过智能技术生成

仅做学习笔记之用。

题目:

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

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

示例 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'] 的一个数字。

思路是这样的:

        事先写好一个有着对应数字的字母表,就像图里那样,放在一个字符串数组中。(要注意数组前两个元素应当是空字符串,因为根据下标,数组的顺序是0,1,2,所以应该从第三个元素开始写。就照着图里那样,打过九键的人应该都明白)

        然后用一个递归方法排列组合,这个方法会为每个数字添加可能的字母,并在每次递归的最后检查是否已经构建了一个完整的组合。如果是,就将其添加到结果列表中。这个过程会一直持续,直到所有可能的组合都被生成出来。

        方法会在每次进入方法中先判断是否已经生成了一条完整的排列,如果是就直接返回。

        然后根据当前数字,找到所有可能的字母组合。(比如题目示例1、3中那样),然后将它们添加到一个StringBuilder的中,记得返回时要toString。然后递归调用,每次传递的是新的StringBuilder和下一个目标数字对应的下标,(不过也没差,我们在数组中已经提前在开头翻个两个空串)

        递归调用返回后,从StringBuilder中移除最后添加的字母,以便尝试其他可能的字母。这个过程称为“回溯”。

有关于回溯:

        (以下内容来自于GPT)            

        回溯算法是一种解决问题的算法,它尝试分步解决一个问题。如果发现当前的步骤不能得到有效的解决方案,它将取消上一步或几步的计算,再尝试其他的可能的选项。回溯算法通常用在解决组合问题、划分问题、排列问题、子集问题等一类需要穷尽所有可能情况的场合。

        回溯算法的核心是“试错”,即当探索到某一步时,发现这一步骤不可能得到最终的正确解答,就退回一步重新尝试其他选项,这个过程可能会递归地重复。

以下是回溯算法的一般步骤:

        1. **选择**:从候选解中选择一个可能的解。在许多问题中,这一步涉及到对当前部分解的扩展。例如,在八皇后问题中,选择一个列放置一个皇后。

        2. **约束**:检查到目前为止的解是否满足问题的约束。如果满足约束,就继续扩展;如果不满足,就放弃这个解。

        3. **目标**:检查到目前为止的解是否满足目标条件。如果满足目标条件,就记录这个解,并继续尝试其他可能的解;如果不满足,就放弃这个解。

        4. **回溯**:如果当前的候选解不能得到有效的解,或者已经尝试完所有可能的候选解,就回退到上一步,尝试其他的候选解。

        回溯算法的关键在于如何设计“选择”和“约束”步骤,以及如何有效地存储和管理已经探索过的部分解,以避免重复计算。

回溯算法的优缺点:

        **优点**:
        - 能够找到问题的所有的解,适用于需要穷尽所有可能性的问题。
        - 可以找到问题的最优解。

        **缺点**:
        - 效率较低,尤其是在解空间很大的时候。
        - 需要消耗大量的内存来存储中间状态。

回溯算法的应用场景:

        - 子集问题,如子集和问题。
        - 排列和组合问题。
        - 字符串匹配问题,如正则表达式匹配。
        - 路径问题,如图的着色问题、旅行商问题(TSP)。
        - 游戏问题,如八皇后问题、数独等。

        回溯算法是一种非常强大且灵活的算法,适用于解决许多复杂的问题。然而,由于它的低效率和高内存消耗,通常需要结合剪枝等优化策略来提高效率。

代码如下:

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

    public List<String> letterCombinations(String digits) {
        List<String> result = new ArrayList<>();
        if (digits == null || digits.isEmpty()) {
            return result;
        }
        create(result, new StringBuilder(), digits, 0);
        return result;
    }

    private void create(List<String> result, StringBuilder current, String digits, int index) {
        if (current.length() == digits.length()) {
            result.add(current.toString());
            return;
        }

        String letters = keyboard[digits.charAt(index) - '0'];
        for (int i = 0; i < letters.length(); i++) {
            current.append(letters.charAt(i));
            create(result, current, digits, index + 1);
            current.deleteCharAt(current.length() - 1);
        }
    }
}

(算法大佬英雄哪里出来曾曰:过——啦)

解决。

  • 21
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值