从零刷算法(9)电话号码的字母组合

148 阅读1分钟

「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战」。

题目描述

给定一个仅包含数字 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'] 的一个数字。

题目链接:[电话号码的字母组合](leetcode-cn.com/problems/3s…)

思路介绍

这道题目是典型的回溯问题。再具体一点,它是典型的排列组合类问题,通常都需要使用回溯的思想去处理。

回溯过程中维护一个字符串,表示已有的字母排列(如果未遍历完电话号码的所有数字,则已有的字母排列是不完整的)。该字符串初始为空。每次取电话号码的一位数字,从哈希表中获得该数字对应的所有可能的字母,并将其中的一个字母插入到已有的字母排列后面,然后继续处理电话号码的后一位数字,直到处理完电话号码中的所有数字,即得到一个完整的字母排列。然后进行回退操作,遍历其余的字母排列。 两个注意事项

前进和后退的状态变化和恢复 寻找递归结束条件

分别根据当前位置的数是几来进行回溯构造字母组合,按键中的值先存在数组中方便取值。 使用到的数据结构的解释如下: ans 存储结果的列表 phone 存储电话按键对应位置的字母String数组,因为数组索引的原因,为了方便根据索引取值,直接将0和1位置的元素置为空串。

代码

class Solution {
    List<String> ans = new ArrayList<>();
    String[] phone = new String[]{"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    public List<String> letterCombinations(String digits) {
        if("".equals(digits)) return ans;
        dfs(digits, 0, new StringBuilder());
        return ans;
    }
    public void dfs(String digits, int start, StringBuilder sb){
        if(start == digits.length()){
            ans.add(new String(sb));
            return;
        }
        // 取出当前数字
        int curIdx = digits.charAt(start) - '0';
        // 当前数字对应的电话按键
        String curPhoneNum = phone[curIdx];
        // 回溯
        for(int i = 0; i < curPhoneNum.length(); i++){
            sb.append(curPhoneNum.charAt(i));
            dfs(digits, start + 1, sb);
            sb.deleteCharAt(sb.length() - 1);
        }
    }
}
​

运行结果

执行结果:

通过

执行用时:0 ms

内存消耗:37.4 MB

时间复杂度:O(2^len(s)) 空间复杂度:O(len(s));

\