【C++】每日一题 17 电话号码的字母组合

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

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

在这里插入图片描述
可以使用回溯法来解决这个问题。首先定义一个映射关系将数字与字母对应起来,然后使用回溯算法来生成所有可能的组合。

回溯算法是一种通过不断尝试各种可能性来解决问题的方法,通常用于求解组合、排列、子集等问题。它通过深度优先搜索的方式探索问题的所有解空间,并在搜索过程中进行剪枝,从而有效地找到满足特定条件的解。

下面是回溯算法的一般步骤:

选择路径: 从问题的初始状态出发,按照某种规则选择一个候选解的路径,即在问题的解空间中前进一步。

探索路径: 在当前选择的路径上继续向前探索,查找可能的解或部分解。

约束条件: 在探索过程中,判断当前路径是否满足问题的约束条件。如果不满足,则放弃该路径,回退到上一步,继续探索其他路径。

标记状态: 在进入下一层递归之前,通常需要修改问题的状态,以便记录当前路径的选择或处理过程。

回退路径: 当探索到底或者无法继续前进时,需要回退到上一层,撤销当前路径的选择,返回上一层继续探索其他路径。

结束条件: 当搜索到达问题的解空间的边界或者满足特定条件时,结束搜索,得到最终的解或者部分解。

回溯算法的核心思想是通过不断地选择、探索、回退和标记状态,逐步地搜索问题的解空间,直到找到所有满足条件的解或者确定无解。

#include <iostream>
#include <vector>
#include <string>using namespace std;// 定义数字与字母的映射关系
vector<string> keypad = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};// 回溯算法生成所有可能的组合
void backtrack(vector<string>& result, string& digits, string current, int index) {// 如果当前组合的长度等于输入数字的长度,则将当前组合加入结果集if (index == digits.length()) {result.push_back(current);return;}// 获取当前数字对应的字母集合string letters = keypad[digits[index] - '0'];// 遍历当前数字对应的每一个字母,进行回溯for (char letter : letters) {current.push_back(letter); // 添加当前字母到当前组合中backtrack(result, digits, current, index + 1); // 递归处理下一个数字current.pop_back(); // 回溯,撤销当前字母}
}vector<string> letterCombinations(string digits) {vector<string> result;if (digits.empty()) return result; // 如果输入为空,则直接返回空结果集string current = "";backtrack(result, digits, current, 0); // 调用回溯算法生成所有可能的组合return result;
}int main() {string digits = "23";vector<string> combinations = letterCombinations(digits);cout << "所有可能的字母组合:" << endl;for (const string& combination : combinations) {cout << combination << " ";}cout << endl;return 0;
}

时间空间复杂度分析

假设输入数字串的长度为 ( n ),每个数字对应的字母集合的平均长度为 ( m )。

时间复杂度分析:
回溯算法:
对于每个数字,我们都需要尝试其对应的所有字母,这需要 ( O(m) ) 的时间。
由于有 ( n ) 个数字,因此总共的时间复杂度为 ( O(m^n) )。
结果集合生成:
生成结果集合的过程中,需要将所有可能的组合添加到结果集中,这也需要 ( O(m^n) ) 的时间。
综合起来,整个算法的时间复杂度为 ( O(m^n) )。

空间复杂度分析:
递归调用栈:
递归调用栈的深度最多为输入数字串的长度 ( n ),因此需要额外的 ( O(n) ) 的空间。
结果集合:
存储结果集合所需的空间取决于结果的数量。最坏情况下,结果数量为 ( O(m^n) ),因此需要 ( O(m^n) ) 的空间。
综合起来,整个算法的空间复杂度为 ( O(m^n) )。

总的来说,这个算法的时间和空间复杂度都是指数级别的,随着输入规模 ( n ) 和每个数字对应的字母集合的大小 ( m ) 的增加,其运行时间和所需空间将急剧增加。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式Linux:编译和使用Protobuf库

目录 1、开发环境和工具 2、安装和编译Protobuf、Protobuf-C库 3、编写和编译proto文件 4、修改makefile文件 5、测试示例 6、参考资料 Protobuf&#xff08;Protocol Buffers&#xff09;是由 Google 开发的一种轻量级、高效的结构化数据序列化方式&#xff0c;用于在不同应用…

内联函数+auto关键字(C++11)+指针空指针nullptr(C++11)

内联函数auto关键字&#xff08;C11&#xff09;指针空指针nullptr&#xff08;C11&#xff09;详解 内联函数概念特性 auto关键字&#xff08;C11&#xff09;auto简介auto的使用细则auto不能推导的场景 基于范围的for循环(C11)范围for的语法范围for的使用条件 指针空指针null…

算法-卡尔曼滤波之卡尔曼滤波的第二个方程:预测方程(状态外推方程)

在上一节中&#xff0c;使用了静态模型&#xff0c;我们推导出了卡尔曼滤波的状态更新方程&#xff0c;但是在实际情况下&#xff0c;系统都是动态&#xff0c;预测阶段&#xff0c;前后时刻的状态是改变的&#xff0c;此时我们引入预测方程&#xff0c;也叫状态外推方程&#…

[动画详解]LeetCode151.翻转字符串里的单词

&#x1f496;&#x1f496;&#x1f496;欢迎来到我的博客&#xff0c;我是anmory&#x1f496;&#x1f496;&#x1f496; 又和大家见面了 欢迎来到动画详解LeetCode算法系列 用通俗易懂的动画让算法题不再神秘 先来自我推荐一波 个人网站欢迎访问以及捐款 推荐阅读 如何低成…

go语言基础1

1.token token是构成源程序的基本不可在分割单元。编译器编译源程序的第一步就是将源程序分割为一个个独立的token&#xff0c;这个过程就是词法分析。Go语言的token可以分为关键字、标识符、操作符、分隔符和字面常量等&#xff0c;如图所示&#xff1a; Go token分隔符有两类…

c#多态性的应用

设计一个电脑游戏&#xff0c;游戏中有猪、牛、兔子、青蛙、鸭子等动物&#xff0c;这些动 物都继承于Vertebrata 类&#xff08;脊椎动物类&#xff09;&#xff0c;Vertebrata类有一个抽象方法Display()&#xff0c;每个动 物都从Vertebrata 类那里继承并重写了Display()方法…

数据驱动测试在接口测试和网站测试中的应用

什么是数据驱动测试 据驱动测试是一种测试方法&#xff0c;其中测试数据和测试逻辑是分开的&#xff0c;测试数据被存储在外部源中&#xff08;如Excel表格、JSON文件、数据库等&#xff09;&#xff0c;测试逻辑则独立于测试数据。在测试过程中&#xff0c;测试数据被读取并传…

ROS2入门21讲__第03讲__ROS2安装方法

目录 前言 Linux系统简介 Ubuntu系统简介 Ubuntu虚拟机安装 1. 下载系统镜像 2. 在虚拟机中创建系统 3. 设置虚拟机硬盘大小 4. 设置Ubuntu镜像路径 5. 启动虚拟机 6. 设置用户名和密码 7. 等待系统安装 8. 完成安装 ROS2系统安装 1. 设置编码 2. 添加源 3. 安装…

2024年5月面试准备

2024年5月面试准备 资料来源Java基础泛型注解异常反射SPI机制Java集合CollectionMap 并发基础线程并发关键字并发集合Lock核心类并发集合核心类原子类核心类线程池核心类ScheduledThreadPoolExecutorForkJoinPoolFokJoinTask JUC原子类: CAS, Unsafe和原子类详解JUC 工具类 Jav…

鸿蒙内核源码分析(内核态锁篇) | 如何实现快锁Futex(下)

本篇为快锁下篇&#xff0c;说清楚快锁在内核态的实现&#xff0c;解答以下问题&#xff0c;它们在上篇的末尾被提出来。 鸿蒙内核进程池默认上限是64个&#xff0c;除去两个内核进程外&#xff0c;剩下的都归属用户进程&#xff0c;理论上用户进程可以创建很多快锁&#xff0…

Android开发,日志级别

5个日志级别 Verbose (VERBOSE): 这是最低的日志级别&#xff0c;用于输出最为详尽的信息&#xff0c;包括开发和调试过程中的各种细节。在Log类中对应的方法是Log.v()。Debug (DEBUG): 此级别用于输出调试信息&#xff0c;帮助开发者理解程序运行流程或状态。通过Log.d()方法…

保研机试之【文件描述符】

A选项&#xff1a; 一个文件描述符对应着系统级文件表中的一项 B选项 C选项 D选项 E选项 F选项 综上&#xff0c;我认为这道题选择B、C、E、F~