算法思路汇总:17.电话号码的字母组合

193 阅读2分钟

17.电话号码的字母组合

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

难度:mid 来源:力扣(LeetCode)

题目:

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

思路:

根据题目知,首先需要对数字和字母进行映射:

Map<String,String> map = Map.of(
    "2","abc","3","def","4","ghi","5","jkl","6","mno","7","pqrs","8","tuv","9","wxyz"
);

套路基本上跟之前的lc77思路相同,其中需要明确的该题处理的范围是两个集合,求的是不同集合间的组合;之前题目的操作属于一个集合。

结构与之前题目相同,该题创建一个结果集一个路径,但是该路径采用的StringBuffer来实现;

List<String> res = new ArrayList<>();
StringBuffer path = new StringBuffer();
  1. 明确结束条件

    遍历完 digits 中的元素,所以需要一个变量来记录元素index,所以我们在初始传入的值为0,index = 0;

    当遍历的下表等于digits长度,那么就开始保存path中的集合元素。

    if(index == digits.length()){
        res.add(path.toString());
        return;
    }
    
  2. 明确单次递归逻辑

    通过index确定digits需要操作的数字和其对应的字母,然后对其字母进行遍历,进行节点的添加、递归、回溯。

    //不同集合间的组合
    String digit = digits.charAt(index)+"";
    String values = map.get(digit);     // 取数字对应的字符集
    for (int i = 0; i < values.length(); i++) {
        path.append(values.charAt(i)); 
        combina(digits, index + 1); // 递归,注意index+1,下层要处理下一个数字了
        path.deleteCharAt(path.length()-1); // 回溯
    }
    

完整代码:

class Solution {
    List<String> res = new ArrayList<>();
    StringBuffer path = new StringBuffer();
    Map<String,String> map = Map.of(
            "2","abc","3","def","4","ghi","5","jkl","6","mno","7","pqrs","8","tuv","9","wxyz"
        );
    public List<String> letterCombinations(String digits) {
        if(digits.length() == 0) return res;
        combina(digits,0);
        return res;
    }
    void combina(String digits,int index){
        if(index == digits.length()){
            res.add(path.toString());
            return;
        }
        //不同集合间的组合
        String digit = digits.charAt(index)+"";
        String values = map.get(digit);     // 取数字对应的字符集
        for (int i = 0; i < values.length(); i++) {
            path.append(values.charAt(i)); 
            combina(digits, index + 1); // 递归,注意index+1,下层要处理下一个数字了
            path.deleteCharAt(path.length()-1); // 回溯
        }
​
    }
}

调试代码如下:

package com.lc;
​
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
​
public class lc17 {
    public static void main(String[] args) {
        letterCombinations("23");
​
    }
    static List<String> res = new ArrayList<>();
    static StringBuffer path = new StringBuffer();
    static Map<String,String> map = Map.of(
            "2","abc","3","def","4","ghi","5","jkl","6","mno","7","pqrs","8","tuv","9","wxyz"
    );
    public static List<String> letterCombinations(String digits) {
        if(digits.length() == 0) return res;
        // if(digits.length() == 1){
        //     String temp = map.get(digits);
        //     for(int i = 0; i < temp.length(); i++){
        //         res.add(temp.charAt(i)+"");
        //     }
        //     return res;
        // }
        combina(digits,0);
        return res;
    }
    static void combina(String digits, int index){
        if(index == digits.length()){
            res.add(path.toString());
            return;
        }
        //不同集合间的组合
        String digit = digits.charAt(index)+"";
        String values = map.get(digit);     // 取数字对应的字符集
        for (int i = 0; i < values.length(); i++) {
            path.append(values.charAt(i));
            combina(digits, index + 1); // 递归,注意index+1,下层要处理下一个数字了
            path.deleteCharAt(path.length()-1); // 回溯
        }
​
    }
}

在此附赠dubug调试视频可供参考:点击进入