LeetCode 17. 电话号码的字母组合 回溯算法

17. 电话号码的字母组合

题目来源

17. 电话号码的字母组合

题目分析

在这道题目中,我们需要将给定的数字字符串 digits 映射到可能的字母组合。具体来说,输入的数字字符串仅包含数字 2-9,每个数字都对应多个字母。题目要求返回所有可能的字母组合。

题目难度

  • 难度:中等

题目标签

  • 标签:哈希表、字符串、回溯

题目限制

  • 0 <= digits.length <= 4
  • digits[i] 是范围 [‘2’, ‘9’] 的一个数字。

解题思路

要解决这个问题,我们可以使用回溯算法。回溯算法能够在树形结构中寻找所有可能的解,其核心在于递归地处理问题的每一层,并在合适的时候回退以探索新的路径。

核心算法步骤

  • 映射关系: 首先,我们需要一个映射来存储每个数字对应的字母集合。这可以通过一个字符串数组 NUMBER_MAP 来实现。

  • 回溯函数: 我们定义一个回溯函数 backtrace,通过递归的方式构造出每一个可能的字母组合。每次递归调用时,我们都会处理index指向的当前数字对应的字母,并向结果集中添加可能的组合。在递归完成后,我们需要“恢复现场”,即回退上一个字符,以便探索新的可能性。

  • 边界条件: 当我们遍历完所有的数字时,将当前的组合加入结果集。

代码实现

以下是实现电话号码字母组合的Java代码:

/**
 * 17. 电话号码的字母组合
 * @param digits 输入的数字串
 * @return ans 所有能表示的字母组合
 */
public List<String> letterCombinations(String digits) {
    List<String> ans = new ArrayList<>();
    if (digits.isEmpty()) {
        return ans;
    }
    backtrace(digits, 0, new StringBuilder(), ans);
    return ans;
}

public void backtrace(String digits, int index, StringBuilder sb, List<String> ans) {
    // 边界条件
    if (index == digits.length()) {
        ans.add(sb.toString());
        return;
    }
    char c = digits.charAt(index);
    for (int i = 0; i < NUMBER_MAP[c - '0'].length(); i++) {
        sb.append(NUMBER_MAP[c - '0'].charAt(i));
        backtrace(digits, index + 1, sb, ans);
        // 恢复现场
        sb.deleteCharAt(sb.length() - 1);
    }
}

代码解读

  • 边界条件: 首先检查输入的 digits 是否为空,如果为空,直接返回空列表。

  • 回溯过程: 对于输入字符串的每个字符,根据映射关系将其对应的字母添加到当前路径中,并递归处理下一个字符。在回溯的过程中,我们不断将已经构造好的组合添加到结果集中。

  • 恢复现场: 每次递归结束后,需要将当前路径的最后一个字符移除,以便尝试新的字母组合。

性能分析

  • 时间复杂度O(4^n),其中 n 是输入字符串的长度。因为每个数字最多对应4个字母,所有可能的组合数量为 4^n

  • 空间复杂度O(n),由于递归调用栈的深度为 n

测试用例

你可以使用以下测试用例来验证代码的正确性:

List<String> result = letterCombinations("23");
System.out.println(result);
// 输出: ["ad","ae","af","bd","be","bf","cd","ce","cf"]

扩展讨论

优化写法

我们可以使用更加简洁的字符串操作,减少不必要的递归调用,进一步优化性能。

其他实现

除了回溯算法,还可以通过迭代的方式逐步构建字母组合,但相对来说代码复杂度会更高。

总结

通过这道题目,我们进一步掌握了回溯算法的应用,尤其是在处理树形结构问题时的优雅解法。通过递归的方式,我们可以有效地生成所有可能的字母组合,并确保不会遗漏任何一种情况。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值