返回

拨开迷雾见彩虹——【LeetCode】电话号码的字母组合Java题解

后端

【LeetCode】电话号码的字母组合Java题解


问题

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

给出数字到字母的映射如下(与电话按键对应):

2 -> "abc"
3 -> "def"
4 -> "ghi"
5 -> "jkl"
6 -> "mno"
7 -> "pqrs"
8 -> "tuv"
9 -> "wxyz"

算法分析

为了解决本问题,我们将采用递归和回溯两种算法进行详细的讲解和示例分析。

递归算法

递归是一种经典的算法设计范式,其核心思想在于将一个问题拆解成若干个规模更小的相同问题,依次解决这些小问题直至最终得到原问题的解。对于本问题,我们可以将电话号码中的每个数字作为递归函数的一个参数,并根据该数字对应的字母进行递归调用,最终得到所有可能的字母组合。

递归算法Java实现

import java.util.ArrayList;
import java.util.List;

class Solution {

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

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

    private void letterCombinationsHelper(String digits, int index, StringBuilder sb, List<String> result) {
        if (index == digits.length()) {
            result.add(sb.toString());
            return;
        }
        int num = digits.charAt(index) - '0';
        String letters = KEYS[num];
        for (int i = 0; i < letters.length(); i++) {
            sb.append(letters.charAt(i));
            letterCombinationsHelper(digits, index + 1, sb, result);
            sb.deleteCharAt(sb.length() - 1);
        }
    }
}

回溯算法

回溯是一种与递归类似的算法设计范式,但其着重于在搜索过程中根据一定条件舍弃某些路径,从而提高算法的效率。对于本问题,我们可以通过回溯算法来减少不必要的重复计算,从而降低时间复杂度。

回溯算法Java实现

import java.util.ArrayList;
import java.util.List;

class Solution {

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

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

    private void backtrack(String digits, int index, StringBuilder sb, List<String> result) {
        if (index == digits.length()) {
            result.add(sb.toString());
            return;
        }
        int num = digits.charAt(index) - '0';
        String letters = KEYS[num];
        for (int i = 0; i < letters.length(); i++) {
            sb.append(letters.charAt(i));
            backtrack(digits, index + 1, sb, result);
            sb.deleteCharAt(sb.length() - 1);
        }
    }
}

复杂度分析

对于本问题,递归和回溯算法的时间复杂度均为O(3^n * 4^m),其中n和m分别代表电话号码中数字2-6和数字7-9的个数。空间复杂度为O(n),其中n为电话号码中的数字个数。

总结

在本文中,我们详细介绍了递归和回溯算法在解决【电话号码的字母组合】问题中的应用,并提供了详细的Java实现代码。读者可以根据自己的需求选择合适的算法来解决该问题,并进一步拓展和应用所学的知识。