leetcode17 电话号码的字母组合
方法1 if-else方法
if-else方法的思路及其简单粗暴,如下图所示,以数字234为例,数字2所对应的字母是abc,数字3所对应的是def,数字4所对应的是ghi,最后所产生的结果就类似于我们中学所学过的树状图一样,从左到右的一组一组生成结果,首先取出数字2的第一个索引对应的a,然后紧接着添加数字3对应的第一个索引的字母d,然后再添加数字4所对应的ghi,分别组成adg、adh、adi,然后一直进行排列组合,直到把所有的结果都列举完,那么就程序就执行完了。
python完整代码:
class Solution:def letterCombinations(self, digits):# 获取输入数字串的长度n = len(digits)result = [] # 用于存储最终的字母组合结果if n == 0:return result # 如果输入为空字符串,则直接返回空列表for i in range(n):self.AddString(result, digits[i])return resultdef AddString(self, result, t): # 定义一个添加字符串的函数n = len(result)letters = ""if t == '2':letters = "abc"elif t == '3':letters = "def"elif t == '4':letters = "ghi"elif t == '5':letters = "jkl"elif t == '6':letters = "mno"elif t == '7':letters = "pqrs"elif t == '8':letters = "tuv"elif t == '9':letters = "wxyz"if n == 0:result.extend(list(letters)) # 如果结果集为空,直接添加第一个数字对应的字母else:temp_result = []for i in range(n): # i表示第一个数字所对应的字母的位置for letter in letters:# 将当前结果集中的每个组合与新的字母组合,得到新的结果集temp_result.append(result[i] + letter)result[:] = temp_result # 用新的结果集替换原有结果集if __name__ == "__main__":solution = Solution()combinations = solution.letterCombinations("234")print(combinations)
c++完整代码:
#include<iostream>
#include<vector>using namespace std;class Solution{
public:vector<string> letterCombinations(string digits){int n = digits.length(); //获取输入数字串的长度vector<string> result; //用于存储最终的字母组合结果if(n == 0){return result;}for(int i=0;i<n;++i){AddString(result, digits[i]); // 调用添加字母函数}return result;}
private:void AddString(vector<string>& result, char digit){int n = result.size();string letters = "";if (digit == '2'){letters = "abc";} else if(digit == '3'){letters = "def";} else if(digit == '4'){letters = "ghi";} else if(digit == '5') {letters = "jkl";} else if(digit == '6'){letters = "mno";} else if(digit == '7'){letters = "pqrs";} else if(digit == '8'){letters = "tuv";} else if(digit == '9'){letters = "wxyz";}if (n == 0){for(char letter : letters){result.push_back(string(1, letter));// 如果结果集为空,直接添加第一个数字对应的字母}} else{vector<string> temp_result;for(int i = 0;i < n; ++i){for(char letter : letters){// 将当前结果集中的每个组合与新的字母组合,得到新的结果集temp_result.push_back(result[i] + letter);}}result = temp_result; // 用新的结果集替换原有结果集}}
};int main(){Solution solution;vector<string> combinations = solution.letterCombinations("234");for(const auto& combination : combinations){cout << combination << endl;}return 0;
}
java完整代码:
import java.util.List;
import java.util.ArrayList;
public class LetterCombinations {public List<String> letterCombinations(String digits) {// 获取输入数字串的长度int n = digits.length();// 用于存储最终的字母组合结果List<String> list = new ArrayList();// 如果输入为空字符串,则直接返回空列表if (n == 0) {return list;}// 遍历每个数字字符for (int i = 0; i < n; i++) {// 调用 StringAdd 函数处理每个数字对应的字母StringAdd(list, digits.charAt(i));}return list;}// 定义一个添加字符串的函数public void StringAdd(List<String> list, char t) {// 获取当前结果集的长度int n = list.size();if(t == '2'){ // 处理数字 2 对应的字母组合if(n==0){list.add("a");list.add("b");list.add("c");}else{for(int i=0;i<n;i++){// 遍历当前结果集,为每个组合添加 'a', 'b', 'c',得到新的结果集list.add(list.get(i)+"a");list.add(list.get(i)+"b");list.add(list.get(i)+"c");}for(int i=0;i<n;i++){list.remove(0);}}// 3}else if(t == '3'){if(n==0){list.add("d");list.add("e");list.add("f");}else{for(int i=0;i<n;i++){// 遍历当前结果集,为每个组合添加 'd', 'e', 'f',得到新的结果集list.add(list.get(i)+"d");list.add(list.get(i)+"e");list.add(list.get(i)+"f");}for(int i=0;i<n;i++){list.remove(0);}}// 4}else if(t == '4'){if(n==0){list.add("g");list.add("h");list.add("i");}else{for(int i=0;i<n;i++){// 遍历当前结果集,为每个组合添加 'g', 'h', 'i',得到新的结果集list.add(list.get(i)+"g");list.add(list.get(i)+"h");list.add(list.get(i)+"i");}for(int i=0;i<n;i++){list.remove(0);}}// 5}else if(t == '5'){if(n==0){list.add("j");list.add("k");list.add("l");}else{for(int i=0;i<n;i++){// 遍历当前结果集,为每个组合添加 'j', 'k', 'l',得到新的结果list.add(list.get(i)+"j");list.add(list.get(i)+"k");list.add(list.get(i)+"l");}for(int i=0;i<n;i++){list.remove(0);}}// 6}else if(t == '6'){if(n==0){list.add("m");list.add("n");list.add("o");}else{for(int i=0;i<n;i++){// 遍历当前结果集,为每个组合添加 'm', 'n', 'o',得到新的结果list.add(list.get(i)+"m");list.add(list.get(i)+"n");list.add(list.get(i)+"o");}for(int i=0;i<n;i++){list.remove(0);}}// 7}else if(t == '7'){if(n==0){list.add("p");list.add("q");list.add("r");list.add("s");}else{for(int i=0;i<n;i++){// 遍历当前结果集,为每个组合添加 'p', 'q', 'r', 's',得到新的结果list.add(list.get(i)+"p");list.add(list.get(i)+"q");list.add(list.get(i)+"r");list.add(list.get(i)+"s");}for(int i=0;i<n;i++){list.remove(0);}}// 8}else if(t == '8'){if(n==0){list.add("t");list.add("u");list.add("v");}else{for(int i=0;i<n;i++){// 遍历当前结果集,为每个组合添加 't', 'u', 'v',得到新的结果list.add(list.get(i)+"t");list.add(list.get(i)+"u");list.add(list.get(i)+"v");}for(int i=0;i<n;i++){list.remove(0);}}// 9}else if(t == '9'){if(n==0){list.add("w");list.add("x");list.add("y");list.add("z");}else{for(int i=0;i<n;i++){// 遍历当前结果集,为每个组合添加 'w', 'x', 'y', 'z',得到新的结果list.add(list.get(i)+"w");list.add(list.get(i)+"x");list.add(list.get(i)+"y");list.add(list.get(i)+"z");}for(int i=0;i<n;i++){list.remove(0);}}}}public static void main(String[] args){LetterCombinations solution = new LetterCombinations();List<String> combinations = solution.letterCombinations("234");System.out.println(combinations);}
}
方法2 回溯法
上面我们讨论了通过列举的方法生成结果,但是发现程序写起来实在是太长了,而且看着很low,那么此时我们就可以把数字组合里面每一个数字所对应的字母组合通过一个篮子(哈希表)存起来,要用哪个就拿哪一个,紧接着再通过回溯的方法进行解决,以下是chatgpt所回答的回溯算法:
回溯算法(Backtracking)是一种通过尝试所有可能的候选解并在找到可行解之前放弃部分(或全部)解空间的策略。在问题的解空间中,通过深度优先搜索,一步一步地探索各个可能的解,当发现当前的部分解不能满足问题的约束条件时,就放弃该部分解,回溯到上一步,继续搜索其他可能的解。
回溯算法通常采用递归的方式实现,每一层递归代表问题的一个阶段,通过递归的深入,逐步构建出问题的解。在搜索过程中,如果当前解不满足问题的条件,则回溯到上一步,尝试其他可能的选择。
典型的回溯问题包括组合问题、排列问题、子集问题等。回溯算法通常用于解决组合优化问题,其中问题的解是某种组合的集合,而且问题通常可以分解为多个子问题,通过递归地解决子问题来构建整体的解。
关键特点:
- 状态空间树: 回溯算法可以通过状态空间树的形式进行表示,每个节点代表问题的一个阶段,树的每一层对应算法的一个递归调用。
- 深度优先搜索: 回溯算法采用深度优先搜索的策略,即一条路走到底,如果发现当前路径不能满足问题的条件,就回溯到上一步。
- 剪枝: 在搜索的过程中,可以通过剪枝来减少搜索空间,提高效率。当发现当前部分解无法满足问题的条件时,可以提前结束搜索。
经典的回溯问题包括八皇后问题、0-1背包问题、图的着色问题等。回溯算法的复杂度通常比较高,因此在设计时需要注意优化搜索空间以提高效率。
但是本题不存在不可行的解,所以通过穷举的方法就可以实现。该方法的思路和上述的方法基本上是一致的。
python完整代码:
class Solution:def letterCombinations(self, digits):# 如果输入为空,则直接返回空列表if not digits:return list()# 定义电话号码到字母的映射关系phoneMap = {"2": "abc","3": "def","4": "ghi","5": "jkl","6": "mno","7": "pqrs","8": "tuv","9": "wxyz",}def backtrack(index):# 当前组合字符串长度等于输入数字串长度时,将其加入结果集if index == len(digits):combinations.append("".join(combination)) # 获取当前数字对应的字母集合else:digit = digits[index] # 将当前字母加入组合字符串,递归调用下一层for letter in phoneMap[digit]:combination.append(letter)backtrack(index + 1)# pop()函数用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值combination.pop() # 当combinations里面存有adg,紧接着执行for letter in phoneMap[digit]:其中digit=4combination = list() # 初始化组合列表和当前组合字符串combinations = list()backtrack(0) # 初始调用回溯函数return combinationsif __name__ == "__main__":# 创建 Solution 对象solution = Solution()# 调用 letterCombinations 函数并输出结果combinations = solution.letterCombinations("234")print(combinations)
class Solution:def letterCombinations(self, digits):# 如果输入为空,则直接返回空列表if not digits:return list()# 定义电话号码到字母的映射关系phoneMap = {"2": "abc","3": "def","4": "ghi","5": "jkl","6": "mno","7": "pqrs","8": "tuv","9": "wxyz",}def backtrack(index):# 当前组合字符串长度等于输入数字串长度时,将其加入结果集if index == len(digits):combinations.append("".join(combination)) # 获取当前数字对应的字母集合else:digit = digits[index] # 将当前字母加入组合字符串,递归调用下一层for letter in phoneMap[digit]:combination.append(letter)backtrack(index + 1)# pop()函数用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值combination.pop() # 当combinations里面存有adg,紧接着执行for letter in phoneMap[digit]:其中digit=4combination = list() # 初始化组合列表和当前组合字符串combinations = list()backtrack(0) # 初始调用回溯函数return combinationsif __name__ == "__main__":# 创建 Solution 对象solution = Solution()# 调用 letterCombinations 函数并输出结果combinations = solution.letterCombinations("234")print(combinations)
c++完整代码:
#include<iostream>
#include<vector>
#include<unordered_map>using namespace std;class Solution{
public:vector<string> letterCombination(string digits){unordered_map<char, string> phoneMap = { // 定义数字对应的字母映射关系{'2', "abc"},{'3', "def"},{'4', "ghi"},{'5', "jkl"},{'6', "mno"},{'7', "pqrs"},{'8', "tuv"},{'9', "wxyz"}};// 处理特殊情况,如果输入为空字符串,则直接返回空列表if(digits.empty()){return vector<string> ();}// 用于存储最终的字母组合结果vector<string> result;// 回溯函数,参数分别为当前数字索引和当前已形成的组合字符串backtrack(digits,0,"",phoneMap,result); //可以试试index等于1是什么结果,就能明白该参数具体指的是什么return result;}
private:// index ---> 数字所对应字母的索引void backtrack(const string& digits, int index, const string& path,const unordered_map<char, string>& phoneMap, vector<string>& result){// 如果当前组合字符串的长度等于输入数字串的长度,将其加入结果集if(index == digits.length()){result.push_back(path);return;}// 获取当前数字对应的字母集合char currentDigit = digits[index];const string& letters = phoneMap.at(currentDigit);// 遍历当前数字对应的字母集合,进行递归回溯for(char letter : letters){// 将当前字母加入组合字符串,递归调用下一层backtrack(digits, index + 1, path + letter, phoneMap, result);}}
};int main(){// 创建 Solution 对象Solution solution;// 调用 letterCombinations 函数并输出结果vector<string> combinations = solution.letterCombination("234");for(const string& combination : combinations){cout << combination << "" << endl;}return 0;
}
java完整代码:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class letterCombinations_1 {public List<String> letterCombinations(String digits) {Map<Character, String> phoneMap = new HashMap<>(); // 定义数字对应的字母映射关系phoneMap.put('2', "abc");phoneMap.put('3', "def");phoneMap.put('4', "ghi");phoneMap.put('5', "jkl");phoneMap.put('6', "mno");phoneMap.put('7', "pqrs");phoneMap.put('8', "tuv");phoneMap.put('9', "wxyz");// 处理特殊情况,如果输入为空字符串,则直接返回空列表if (digits == null || digits.isEmpty()) {return new ArrayList<>();}// 用于存储最终的字母组合结果List<String> result = new ArrayList<>();// 回溯函数,参数分别为当前数字索引和当前已形成的组合字符串backtrack(digits, 0, "", phoneMap, result);return result;}private void backtrack(String digits, int index, String path,Map<Character, String> phoneMap, List<String> result) {// 如果当前组合字符串的长度等于输入数字串的长度,将其加入结果集if (index == digits.length()) {result.add(path);return;}// 获取当前数字对应的字母集合char currentDigit = digits.charAt(index);String letters = phoneMap.get(currentDigit);// 遍历当前数字对应的字母集合,进行递归回溯for (char letter : letters.toCharArray()) {// 将当前字母加入组合字符串,递归调用下一层backtrack(digits, index + 1, path + letter, phoneMap, result);}}public static void main(String[] args) {// 创建 Solution 对象letterCombinations_1 solution = new letterCombinations_1();// 调用 letterCombinations 函数并输出结果List<String> combinations = solution.letterCombinations("234");for (String combination : combinations) {System.out.println(combination);}}
}
相关文章:

leetcode17 电话号码的字母组合
方法1 if-else方法 if-else方法的思路及其简单粗暴,如下图所示,以数字234为例,数字2所对应的字母是abc,数字3所对应的是def,数字4所对应的是ghi,最后所产生的结果就类似于我们中学所学过的树状图一样&…...

用html和css实现一个加载页面【究极简单】
要创建一个简单的加载页面,你可以使用 HTML 和 CSS 来设计。以下是一个基本的加载页面示例: HTML 文件 (index.html): <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"…...
Android-消息机制Handler
Handler的机制:Android 消息传递机制就是handler。在多线程的应用场景中,将工作线程中需更新UI的操作信息 传递到 UI主线程,从而实现对UI的更新处理,最终实现异步消息的处理。多个线程并发更新UI的同时 保证线程安全。Handler只是一个入口&am…...

MySQL夯实之路-事务详解
事务四大特性 事务需要通过严格的acid测试。Acid表示原子性,一致性,隔离性,持久性。 原子性(atomicity) 事务是不可分割的最小单元,对于整个事务的操作,要么全部提交成功,要么全部…...

安泰电子前置微小信号放大器怎么用的
前置微小信号放大器是一种重要的电子设备,用于放大微弱的输入信号,提高系统的灵敏度。它在各种领域中都有广泛的应用,包括音频、通信、测量等。在这篇文章中,我们将详细介绍前置微小信号放大器的使用方法,以便更好地理…...

【深度学习每日小知识】Overfitting 过拟合
过拟合是机器学习(ML)中的常见问题,是指模型过于复杂,泛化能力较差的场景。当模型在有限数量的数据上进行训练,并且学习了特定于该特定数据集的模式,而不是适用于新的、看不见的数据的一般模式时࿰…...

嵌入式必备的WEB知识
写在前面 嵌入式要学习Wed前端吗?答案是要的,不需要深入学习,只需要简单了解即可。为什么要学习? 原因如下: 可以远程控制和管理设备:通过简单的Web知识,嵌入式系统可以建立Web界面,…...
Scipy 中级教程——信号处理
Python Scipy 中级教程:信号处理 Scipy 的信号处理模块提供了丰富的工具,用于处理和分析信号数据。在本篇博客中,我们将深入介绍 Scipy 中的信号处理功能,并通过实例演示如何应用这些工具。 1. 信号生成与可视化 首先ÿ…...

【排序篇2】选择排序、计数排序
目录 一、选择排序二、计数排序 一、选择排序 整体思想: 从数组中选出最小值和最大值放在起始位置,直到排序完成 具体步骤: 定义两个变量begin和end为下标,指向数组始末定义要找的最大值的下标为maxi,最小值的下标为…...

重生奇迹mu敏弓加点攻略
1. 选择正确的属性点分配 在重生奇迹mu游戏中敏弓的属性点分配非常重要。建议将主要属性点分配在敏捷和力量上这样可以提高敏弓的攻击力和闪避能力。适当加点在体力和魔力上可以提高敏弓的生存能力和技能释放次数。不要忘记适当加点在智力上可以提高敏弓的技能威力和命中率。 …...

用通俗易懂的方式讲解:一文讲透主流大语言模型的技术原理细节
大家好,今天的文章分享三个方面的内容: 1、比较 LLaMA、ChatGLM、Falcon 等大语言模型的细节:tokenizer、位置编码、Layer Normalization、激活函数等。 2、大语言模型的分布式训练技术:数据并行、张量模型并行、流水线并行、3D …...

通过IP地址识别风险用户
随着互联网的迅猛发展,网络安全成为企业和个人关注的焦点之一。识别和防范潜在的风险用户是维护网络安全的关键环节之一。IP数据云将探讨通过IP地址识别风险用户的方法和意义。 IP地址的基本概念:IP地址是互联网上设备的独特标识符,它分为IP…...
汇编和C语言转换
C语言和汇编语言之间有什么区别 C语言和汇编语言之间存在显著的区别,主要体现在以下几个方面: 抽象层次: 汇编语言:更接近硬件的低级语言,通常与特定的处理器或指令集紧密相关。它提供了对处理器指令的直接控制,允许程序员直接操作硬件资源,如寄存器、内存等。 C语言:…...
【IOS】惯性导航详解(包含角度、加速度、修正方式的api分析)
参考文献 iPhone的惯性导航,基于步态。https://www.docin.com/p-811792664.html Inertial Odometry on Handheld Smartphones: https://arxiv.org/pdf/1703.00154.pdf 惯性导航项目相关代码:https://github.com/topics/inertial-navigation-systems use…...

Self-Attention
前置知识:RNN,Attention机制 在一般任务的Encoder-Decoder框架中,输入Source和输出Target内容是不一样的,比如对于英-中机器翻译来说,Source是英文句子,Target是对应的翻译出的中文句子,Attent…...

网络协议与攻击模拟_04ICMP协议与ICMP重定向
ICMP协议是网络层协议, 利用ICMP协议可以实现网络中监听服务和拒绝服务,如 ICMP重定向的攻击。 一、ICMP基本概念 1、ICMP协议 ICMP是Internet控制报文协议,用于在IP主机、路由器之间传递控制消息,控制消息指网络通不通、主机是…...
pytest-mock 数据模拟
文章目录 mock 测试unittest.mockMock类MagicMock类patch装饰器create_autospec函数断言的方法 pytest-mock 使用 mock 测试 在单元测试时,有些数据需要依赖其他服务或者不好获取到,此时需要使用mock来模拟对应的函数、对象等。 mock模拟数据的python…...

单片机原理及应用:定时器/计数器综合应用
本文是《单片机原理及应用》专栏中的最后一篇文章,笔者以编译器的安装配置——51单片机简介——LED和数码管外设——开关和按键控制功能切换——外部中断系统——定时器与计数器为知识大纲,介绍了C语言编程控制51单片机的入门教程。作为收尾,…...

R语言【paleobioDB】——pbdb_intervals():通过参数选择,返回多个地层年代段的基本信息
Package paleobioDB version 0.7.0 paleobioDB 包在2020年已经停止更新,该包依赖PBDB v1 API。 可以选择在Index of /src/contrib/Archive/paleobioDB (r-project.org)下载安装包后,执行本地安装。 Usage pbdb_interval (id, ...) Arguments 参数【..…...

阅读笔记lv.1
阅读笔记 sql中各种 count结论不同存储引擎计算方式区别count() 类型 责任链模式常见场景例子(闯关游戏) sql中各种 count 结论 innodb count(*) ≈ count(1) > count(主键id) > count(普通索引列) > count(未加索引列)myisam 有专门字段记录…...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
在 Kubernetes 集群中,如何在保障应用高可用的同时有效地管理资源,一直是运维人员和开发者关注的重点。随着微服务架构的普及,集群内各个服务的负载波动日趋明显,传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...
人工智能 - 在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型
在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型。这些平台各有侧重,适用场景差异显著。下面我将从核心功能定位、典型应用场景、真实体验痛点、选型决策关键点进行拆解,并提供具体场景下的推荐方案。 一、核心功能定位速览 平台核心定位技术栈亮…...

何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践,很多人以为AI已经强大到不需要程序员了,其实不是,AI更加需要程序员,普通人…...

GraphRAG优化新思路-开源的ROGRAG框架
目前的如微软开源的GraphRAG的工作流程都较为复杂,难以孤立地评估各个组件的贡献,传统的检索方法在处理复杂推理任务时可能不够有效,特别是在需要理解实体间关系或多跳知识的情况下。先说结论,看完后感觉这个框架性能上不会比Grap…...
Spring事务传播机制有哪些?
导语: Spring事务传播机制是后端面试中的必考知识点,特别容易出现在“项目细节挖掘”阶段。面试官通过它来判断你是否真正理解事务控制的本质与异常传播机制。本文将从实战与源码角度出发,全面剖析Spring事务传播机制,帮助你答得有…...
[特殊字符] Spring Boot底层原理深度解析与高级面试题精析
一、Spring Boot底层原理详解 Spring Boot的核心设计哲学是约定优于配置和自动装配,通过简化传统Spring应用的初始化和配置流程,显著提升开发效率。其底层原理可拆解为以下核心机制: 自动装配(Auto-Configuration) 核…...

Yolo11改进策略:Block改进|FCM,特征互补映射模块|AAAI 2025|即插即用
1 论文信息 FBRT-YOLO(Faster and Better for Real-Time Aerial Image Detection)是由北京理工大学团队提出的专用于航拍图像实时目标检测的创新框架,发表于AAAI 2025。论文针对航拍场景中小目标检测的核心难题展开研究,重点解决…...