Loading

电话号码的字母组合

1.问题描述

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

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

示例:

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

说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。

2.求解

回溯解法

回溯法是从根结点出发,以深度优先的方式搜索的一种算法。

  • 首先使用哈希表存储每个数字对应的所有可能的字母,然后进行回溯操作。

  • 每次取电话号码的一位数字,将其中的一个字母插入到字符串后面,然后继续处理下一位数字,一直到数字处理完成。

  • 此时便拿到了一个完整的字符串组合,然后进行回退操作,遍历其余的字母序列。

本题中需要在循环中嵌套递归调用。

代码如下
	List<String> list = new ArrayList<>();
    String[] letter_map = {" ", "*", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

    public List<String> letterCombinations(String digits) {
        if (digits == null || digits.length() == 0) {
            return list;
        }
        iterStr(digits, new StringBuilder(), 0);
        return list;
    }

    void iterStr(String digits, StringBuilder stringBuilder, int index) {
        if (index == digits.length()) {
            list.add(stringBuilder.toString());
            return;
        }
        char c = digits.charAt(index);
        int num = c - '0';
        String s = letter_map[num];
        for (int i = 0; i < s.length(); i++) {
            stringBuilder.append(s.charAt(i));
            iterStr(digits, stringBuilder, index+1);
            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
        }

    }
  • 时间复杂度为遍历字母组合的总数为O(3m×4n),其中m 是输入中对应 33 个字母的数字个数(包括数字 22、33、44、55、66、88),nn 是输入中对应 44 个字母的数字个数(包括数字 77、99)。
  • 空间复杂度O(m + n),即输入数字的总个数。

几个小知识点

队列解法

利用队列先进先出,将之前的字符串出队,拼接新的字符,新生成的字符串入队。

代码如下
public List<String> letterCombinations(String digits) {
    LinkedList<String> ans = new LinkedList<String>();
    if (digits.isEmpty()) return ans;
    String[] mapping = new String[]{"0", "1", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    ans.add("");
    for (int i = 0; i < digits.length(); i++) {
        int x = Character.getNumericValue(digits.charAt(i));
        while (ans.peek().length() == i) {
            String t = ans.remove();
            for (char s : mapping[x].toCharArray())
                ans.add(t + s);
        }
    }
    return ans;
}
  • likList.peek方法

    该方法返回头对象或元素(即,它返回列表中唯一的第一个元素)。 如果列表为空,则不会给出任何异常。

  • 为什么使用LinkList

posted @ 2020-09-30 11:04  水纸杯  阅读(569)  评论(0)    收藏  举报