LeetCode、17. 电话号码的字母组合【中等,dfs回溯】

文章目录

前言

博主介绍:✌目前全网粉丝2W+,csdn博客专家、Java领域优质创作者,博客之星、阿里云平台优质作者、专注于Java后端技术领域。

涵盖技术内容:Java后端、算法、分布式微服务、中间件、前端、运维、ROS等。

博主所有博客文件目录索引:博客目录索引(持续更新)

视频平台:b站-Coder长路


LeetCode、17. 电话号码的字母组合【中等,dfs回溯】

题目与类型

学习:leetcode题解

题目链接:17. 电话号码的字母组合

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

题目类型:搜索与图论/回溯、基础算法/枚举

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


思路

本题是要得到所有电话号码的字母组合,这实际上就是全排列(dfs),其中就包含回溯的一个操作处理,我们可以使用一个临时保留或者尝试使用回溯思路来实现。


递归+回溯

思路:由于循环的个数不确定,则需要使用递归来进行求解。

代码 :时间复杂度O (3m ×4n)、空间复杂度O(m+n)

java 复制代码
class Solution {

    /**
     * 根据指定字符生成字符串
     * @param ch 数字字符
     * @return
     */
    public String generateNumtoString(char ch){
        String[] arr = new String[] {
            "abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"
        };
        if (ch - '2' <= arr.length){
            return arr[ch - '2'];
        }
        return null;
    }

    private List<String> letters = new ArrayList<>();


    /**
     * 全排列 :abc、def、ghip
     * @param arr 数组集合
     * @param curIndex 当前要遍历的指定数组
     * @param curArrIndex 当前排列的个数
     * @param genStr 当前生成的字符串
     */
    public void quanpailie(String[] arr, int curIndex, int curArrIndex, String genStr){
        //生成每组的排列个数
        if(curArrIndex == arr.length){
            letters.add(genStr);
            return;
        }
        String curArr = arr[curIndex];//取得当前要遍历的数组
        String temp = genStr; //临时保存原先状态
        for (int i = 0; i < curArr.length(); i++) { //枚举所有情况
            genStr += curArr.charAt(i);
            quanpailie(arr,curIndex + 1, curArrIndex + 1, genStr);
            genStr = temp; //回溯
        }
    }

    public List<String> letterCombinations(String digits) {
        if (Objects.equals("",digits)){
            return new ArrayList<>();
        }
        String[] arrs = new String[digits.length()];
        for (int i = 0; i < digits.length(); i++) {
            arrs[i] = generateNumtoString(digits.charAt(i));
        }
        //使用全排列进行求解
        quanpailie(arrs,0, 0, "");
        return letters;
    }

}

小优化:对于回溯操作的字符串替换使用StringBuilder,时间、空间效率大幅度提升!

java 复制代码
public void quanpailie(String[] arr, int curIndex, int curArrIndex, StringBuilder str){
    ...
    for (int i = 0; i < curArr.length(); i++) { 
        str.append(curArr.charAt(i));
        ...
        str.deleteCharAt(curArrIndex);//回溯优化
    }
}

优化:StringBuilder来回溯

思路:核心优化点就是在字符串回溯、拼接上

java 复制代码
/**
     * 根据指定字符生成字符串
     * @param ch 数字字符
     * @return
     */
public String generateNumToStr(char ch){
    String[] arr = new String[] {
        "abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"
    };
    if (ch - '2' <= arr.length){
        return arr[ch - '2'];
    }
    return null;
}

private List<String> letters = new ArrayList<>();

/**
     * 全排列 :abc、def、ghip
     * @param phones 电话数字映射的字符串数组
     * @param index 当前排列的数字位置
     * @param genStr 当前生成的字符串
     */
public void quanpailie(String[] phones, int index, StringBuilder genStr){
    //生成每组的排列个数
    if(index == phones.length){
        letters.add(genStr.toString());
        return;
    }
    String curArr = phones[index];//取得当前要遍历的数组
    for (int i = 0; i < curArr.length(); i++) { //枚举所有情况
        genStr.append(curArr.charAt(i));
        quanpailie(phones,index + 1, genStr);
        genStr.deleteCharAt(index);
    }
}

public List<String> letterCombinations(String digits) {
    if (Objects.equals("",digits)){
        return new ArrayList<>();
    }
    String[] arrs = new String[digits.length()];
    for (int i = 0; i < digits.length(); i++) {
        arrs[i] = generateNumToStr(digits.charAt(i));
    }
    //使用全排列进行求解
    quanpailie(arrs,0, new StringBuilder(""));
    return letters;
}

补充代码:2024.1.31(简化)

java 复制代码
class Solution {

    List<String> res = new ArrayList<>();

    //"23"
    public List<String> letterCombinations(String digits) {
        if ("".equals(digits)) return res;
        //2-9
        String[] phones = {"abc","def","ghi","jkl", "mno","pqrs","tuv","wxyz"};
        List<String> phoneList = new ArrayList<>();
        for (int i = 0; i < digits.length(); i++) {
            char ch = digits.charAt(i);
            int num = ch - '0';
            if (num < 2) continue;
            phoneList.add(phones[num - 2]);
        }
        dfs (0, digits.length(), new StringBuilder(),  phoneList);
        return res;

    }

    public void dfs (int curLevel, int allLevel, StringBuilder str, List<String> phoneList) {
        //若是层数已经超越了原本的电话拨号数,那么直接添加到集合中
        if (curLevel >= allLevel) {
            res.add(str.toString());
            return;
        }
        //当前层编号
        String phones = phoneList.get(curLevel);
        for (int i = 0; i < phones.length(); i++) {
            str.append(phones.charAt(i));
            dfs (curLevel + 1, allLevel, str, phoneList);
            str.deleteCharAt(str.length() - 1);//回溯
        }
    }
}

资料获取

大家点赞、收藏、关注、评论啦~

精彩专栏推荐订阅:在下方专栏👇🏻

更多博客与资料可查看👇🏻获取联系方式👇🏻,🍅文末获取开发资源及更多资源博客获取🍅


整理者:长路 时间:2024.1.31

相关推荐
磊 子1 分钟前
STL之set以及set和map区别
开发语言·c++·算法
Promise微笑11 分钟前
算法突围:“双核四驱”理论下的“官网”AI引用概率提升指南
人工智能·算法·chatgpt
KaMeidebaby17 分钟前
卡梅德生物技术快报|免疫共沉淀 - Co-IP 实验在转录因子 ATF3/Smad4 蛋白互作研究中的应用实例解析
网络·人工智能·网络协议·tcp/ip·其他·算法·新浪微博
wayz1121 分钟前
20260530 软件ETF(159852)量化分析
算法·金融·数据分析·量化交易
通信小呆呆36 分钟前
Hankel结构及其快速算法详解
线性代数·算法·机器学习
四代水门36 分钟前
服务端倒带(Server-Side Rewind)命中判定系统
java·前端·算法
吃好睡好便好38 分钟前
矩阵的左除和右除
人工智能·学习·线性代数·算法·矩阵
江屿风43 分钟前
C++图的基本概念流食般投喂-竞赛编
开发语言·数据结构·c++·笔记·算法·图论
Halo_tjn1 小时前
JDBC 技术的使用
java·算法
Byte不洛1 小时前
哈希表原理 + 冲突解决 + C++实现
数据结构·c++·算法·哈希算法·散列表