LeetCode - 17 电话号码的字母组合

news2024/11/13 22:41:50

题目来源

17. 电话号码的字母组合 - 力扣(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'] 的一个数字。

题目解析

本题是一个组合问题,可以使用回溯算法解题。

什么是组合问题?

以示例一为例:digits = "23",其中:

  • "2" 对应的可选字母有:['a', 'b', 'c']
  • “3” 对应的可选字母有:['d', 'e', 'f']

因此 "23" 对应的组合有:"ad"、"ae"、"af"、"bd"、"be"、"bf"、"cd"、"ce"、"cf"

如果画图表示的话,可以发现组合问题的求解过程,可以形成一个树形结构。

该树形结构的每一条根到叶子节点的路径都对应一个组合。

因此,如果我们可以遍历出该树形结构的每一条分支,那么就能求出所有组合。

我们可以使用深搜DFS来遍历出树的每一条分支,而深搜本质来说是一种回溯算法。关于回溯算法可以看下:

带你学透回溯算法(理论篇)| 回溯法精讲!_哔哩哔哩_bilibili

C源码实现

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
char *dic[] = {"", "", "abc", "def", "ghi",
               "jkl", "mno", "pqrs", "tuv", "wxyz"};

// 记录所有组合
char **results;
int results_size;

// 用于记录某个组合的临时容器
char path[5] = {'\0'};
int path_size = 0;

/**
 * 回溯算法
 * @param index 表示当前找的是组合的第index个元素
 * @param digits 原始串
 */
void dfs(int index, char *digits) {
    if (path_size == strlen(digits)) { // 组合元素数量达标
        results[results_size] = (char *) calloc(5, sizeof(char));
        strcpy(results[results_size++], path); // 将临时组合记录进结果集
        return;
    }

    // 第index层可选的字母
    char *letters = dic[digits[index] - '0'];

    // 第index层的每一个字母都参与形成组合
    for (int i = 0; i < strlen(letters); i++) {
        path[path_size++] = letters[i]; // 字母letters[i]加入组合
        dfs(index + 1, digits); // 继续进入下层
        path[--path_size] = '\0'; // 回溯
    }
}

char **letterCombinations(char *digits, int *returnSize) {
    // digits长度最大4, 每个数字最多对应4个字母,因此最多产生 4 * 4 * 4 * 4 个组合
    results = (char **) calloc(256, sizeof(char *));
    results_size = 0;

    if (strlen(digits) != 0) {
        dfs(0, digits);
    }

    *returnSize = results_size;
    return results;
}

C++算法源码

class Solution {
public:
    vector<string> dic = {"", "", "abc", "def", "ghi",
                          "jkl", "mno", "pqrs", "tuv", "wxyz"};

    vector<string> letterCombinations(string digits) {
        vector<string> results;

        if (!digits.empty()) {
            dfs(0, "", digits, results);
        }

        return results;
    }

    /**
     * 回溯算法
     * @param index 表示当前找的是组合的第index个元素
     * @param path 用于记录某个组合的临时容器
     * @param digits 原始串
     * @param results 记录所有组合的结果集
     */
    void dfs(int index, string path, string digits, vector<string> &results) {
        if (path.length() == digits.length()) { // 组合元素数量达标
            results.emplace_back(path); // 将临时组合记录进结果集
            return;
        }

        // 第index层可选的字母
        string letters = dic[digits[index] - '0'];

        // 第index层的每一个字母都参与形成组合
        for (int i = 0; i < letters.length(); i++) {
            path.push_back(letters[i]); // 字母letters[i]加入组合
            dfs(index + 1, path, digits, results); // 继续进入下层
            path.pop_back(); // 回溯
        }
    }
};

Java源码实现

class Solution {
    String[] dic = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

    public List<String> letterCombinations(String digits) {
        ArrayList<String> results = new ArrayList<>();

        if (!digits.isEmpty()) {
            dfs(0, new StringBuilder(), digits, results);
        }

        return results;
    }

    /**
     * 回溯算法
     *
     * @param index   表示当前找的是组合的第index个元素
     * @param path    用于记录某个组合的临时容器
     * @param digits  原始串
     * @param results 记录所有组合的结果集
     */
    public void dfs(int index, StringBuilder path, String digits, ArrayList<String> results) {
        if (path.length() == digits.length()) { // 组合元素数量达标
            results.add(path.toString()); // 将临时组合记录进结果集
            return;
        }

        // 第index层可选的字母
        String letters = dic[digits.charAt(index) - '0'];

        // 第index层的每一个字母都参与形成组合
        for (int j = 0; j < letters.length(); j++) {
            path.append(letters.charAt(j)); // 字母letters[i]加入组合
            dfs(index + 1, path, digits, results); // 继续进入下层
            path.deleteCharAt(path.length() - 1);  // 回溯
        }
    }
}

Python源码实现

dic = ("", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz")


def dfs(index, path, digits, results):
    """
    回溯算法
    :param index: 表示当前找的是组合的第index个元素
    :param path: 用于记录某个组合的临时容器
    :param digits: 原始串
    :param results: 记录所有组合的结果集
    :return: void
    """
    if len(path) == len(digits):  # 组合元素数量达标
        results.append("".join(path))  # 将临时组合记录进结果集
        return

    # 第index层可选的字母
    letters = dic[int(digits[index])]

    # 第index层的每一个字母都参与形成组合
    for i in range(len(letters)):
        path.append(letters[i])  # 字母letters[i]加入组合
        dfs(index + 1, path, digits, results)  # 继续进入下层
        path.pop()  # 回溯


class Solution(object):
    def letterCombinations(self, digits):
        """
        :type digits: str
        :rtype: List[str]
        """
        results = []

        if len(digits) > 0:
            dfs(0, [], digits, results)

        return results

JavaScript源码实现

/**
 * @param {string} digits
 * @return {string[]}
 */
const dic = ["", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"];

var letterCombinations = function (digits) {
    const results = [];

    if (digits.length > 0) {
        dfs(0, [], digits, results);
    }

    return results;
};

/**
 * 回溯算法
 * @param {*} index 表示当前找的是组合的第index个元素
 * @param {*} path 用于记录某个组合的临时容器
 * @param {*} digits 原始串
 * @param {*} results 记录所有组合的结果集
 * @returns void
 */
function dfs(index, path, digits, results) {
    if (path.length == digits.length) { // 组合元素数量达标
        results.push(path.join("")); // 将临时组合记录进结果集
        return;
    }

    // 第index层可选的字母
    const letters = dic[parseInt(digits[index])];

    for (let i = 0; i < letters.length; i++) {
        path.push(letters[i]); // 字母letters[i]加入组合
        dfs(index + 1, path, digits, results); // 继续进入下层
        path.pop();  // 回溯
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2127220.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

共享单车轨迹数据分析:以厦门市共享单车数据为例(三)

本篇文章将视角聚焦于共享单车的出行距离和时间分布&#xff0c;为了更好地理解共享单车在特定时间段内的使用情况及用户行为特征&#xff0c;本文基于2020年12月21日上午06:00至10:00期间收集的共享单车订单数据进行了详细的分析&#xff0c;旨在探索共享单车在该时间段内的出…

Centos7 Hadoop 单机版安装教程(图文)

本章教程,主要记录如何在Centos7中安装Hadoop单机版。 一、软件安装包和基础环境 CentOS7.x,jdk8,hadoop 通过网盘分享的文件:Hadoop 链接: https://pan.baidu.com/s/1_qGI9QeXMAJNb3TydHhQGA?pwd=xnz4 提取码: xnz4 当然你也可以自己去官网下载。 java8:https://www.ora…

【Python第三方库】OpenCV库实用指南

文章目录 前言安装OpenCV读取图像图像基本操作获取图像信息裁剪图像图像缩放图像转换为灰度图图像模糊处理边缘检测图像翻转图像保存 视频相关操作方法讲解读取视频从摄像头读取视频 前言 OpenCV&#xff08;Open Source Computer Vision Library&#xff09;作为一个强大的计…

使用docker配置wordpress

docker的安装 配置docker yum源 sudo yum install -y yum-utils sudo yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo下载最新版本docker sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-…

基于spring拦截器实现博客项目的强制登录功能(四)

6. 强制登录 当⽤⼾访问 博客列表和博客详情⻚ 时, 如果⽤⼾当前尚未登陆, 就⾃动跳转到登陆⻚⾯. 我们可以采⽤拦截器来完成, token通常由前端放在header中, 我们从header中获取token, 并校验 token是否合法 6.1 添加拦截器 package com.example.spring_blog_24_9_8.config;…

k8s dashboard token 生成/获取

创建示例用户 在本指南中&#xff0c;我们将了解如何使用 Kubernetes 的服务帐户机制创建新用户、授予该用户管理员权限并使用与该用户绑定的承载令牌登录仪表板。 对于以下每个和的代码片段ServiceAccount&#xff0c;ClusterRoleBinding您都应该将它们复制到新的清单文件(如)…

Blazor开发框架Known-V2.0.10

Known今天迎来了2.0的第11个版本&#xff0c;同时网站网址和板块也进行了一次升级改造&#xff0c;虽不完美&#xff0c;但一直在努力改变&#xff0c;之前一直在完善框架功能&#xff0c;忽略了文档的重要性&#xff0c;所以这次更新了文档和API。交流互动板块也在进行当中&am…

PPT幻灯片的添加与编辑:全面技术指南

目录 一、PPT幻灯片的添加 1.1 启动PowerPoint与新建演示文稿 1.2 选择模板 1.3 添加新幻灯片 1.3.1 使用“开始”选项卡 1.3.2 使用快捷键 1.3.3 复制现有幻灯片 1.4 调整幻灯片顺序 二、PPT幻灯片的编辑 2.1 输入与编辑文本 2.1.1 使用文本框添加文本 2.1.2 使用占…

GitHub Star 数量前 13 的自托管项目清单

一个多月前&#xff0c;我们撰写并发布了这篇文章《终极自托管解决方案指南》。在那篇文章里我们深入探讨了云端服务与自托管方案的对比、自托管的潜在挑战、如何选择适合自托管解决方案&#xff0c;并深入介绍了五款涵盖不同场景的优秀自托管产品。 关于自托管的优势&#xf…

职业技能大赛背景下的移动互联网应用软件开发(Android)实训室建设方案

一、建设背景 随着科技的持续进步&#xff0c;移动设备已成为人们日常生活中不可或缺的一部分。据相关数据&#xff0c;移动互联网的使用率在近年来显著上升。在这样的背景下&#xff0c;移动互联技术不仅推动了科技的发展&#xff0c;也渗透到了智能家居、车联网、工业自动化…

大数据-129 - Flink CEP 详解 Complex Event Processing - 复杂事件处理

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

改进版field-sensitive指针分析算法

DEA 1.Introduction2.Approach2.1.Stride-based Field Representation2.1.1.示例12.1.2.示例2 2.2.完整算法 3.Evaluation3.1.Implementation3.2.结果 参考文献 1.Introduction 这篇paper是SVF团队对PKH field-sensitive指针分析算法 [ 2 ] ^{[2]} [2] 的优化&#xff0c;在使…

Pycharm中python文件导入torch模块时报错:No module named ‘torch‘

问题描述 导入torch时报错 上网查找后&#xff0c;发现原因可能是没有安装pytorch&#xff0c;但检查后发现自己已经安装了&#xff0c;遂考虑到可能是没有使用正确的环境 解决方法 因为是PyCharm 没有使用我所安装了 PyTorch 的 Conda 环境&#xff0c;所以报错了&#xf…

计算2的100次方

#include <stdio.h>int main() {int a[100] {0};a[0] 1;for(int i 0;i < 100;i)//乘100次2{for(int j 0; j < 100;j)//乘以每一位{a[j] * 2;//每一位都*2}for(int k 0;k < 99;k){if(a[k] > 10)//判断进位{a[k 1];a[k] - 10;}}}//找到第一个不为0的数&a…

vue part 9

动画与过渡 Test.vue <template><div><button click"isShow !isShow">显示/隐藏</button><transition name"hello" appear><h1 v-show"isShow">你好啊!</h1></transition><transition …

51单片机快速入门之点灯 STC 51单片机

第一步创建工程 第二步加载头文件 第三步编写代码 点灯完成 解释:主函数为main() 内部P1控制的是p1.0-p1.7 引脚 0为低电平

银河麒麟国产化系统(或者是Linux)一键安装docker和docker-compose

在国产化化机器上离线安装docker和docker-compose 第一步&#xff0c;查询国产化系统的cpu架构 使用如下命令都可以查询出来&#xff1a; # 查询全部 uname -a # 只查询部分 uname -p # 查了cpu 列表 lscpu 查询示例如下&#xff1a; 为麒麟桌面版 为麒麟服务版 第二步&a…

人工智能领域各方向顶级会议和期刊

会议 人工智能基础与综合&#xff1a;AAAI、CICAI (!)、UAI、IJCAI 机器学习&#xff1a;COLT、ICLR、ICML、NeurIPS 模式识别与计算机视觉&#xff1a;ECCV、CVPR、ICCV 语言与语音处理&#xff1a;ACL、EMNLP 知识工程与数据挖掘&#xff1a;SIGKDD、SIGMOD、ICDE、SIGIR、V…

golang-基础知识(array, slice, map)

1. array array就是数组&#xff0c;我们可以通过如下方式定义一个数组并对数组中的元素进行赋值 var arr [n]type // 定义一个大小为n&#xff0c;类型为type的数组 arr[0] xx // 对数组中的元素进行赋值 其中[n]type中&#xff0c;n表示数组的长度&#xff0c;type表示数…

【数字】xilinx的AXI VIP如何使用的guide

AXI 验证 IP (VIP)AXI Stream VIP 可用于为支持定制 RTL 设计流程的 AXI 主设备及 AXI 从设备验证连接和基本功能性。此外&#xff0c;它还支持贯通模式&#xff0c;该模式明显有助于用户监控事务处理信息&#xff0f;吞吐量或驱动有源激励。AXI VIP 提供的实例测试台和测试可演…