电话号码的字母组合
难度:
标签:
题目描述
给定一个仅包含数字 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']
的一个数字。
代码结果
运行时间: 44 ms, 内存: 15 MB
/**
* Problem: Given a string containing digits from 2-9, return all possible letter combinations that the number could represent.
* Approach: Use Java Stream and recursive function to generate all possible combinations.
*/
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Solution {
// Mapping of digits to corresponding letters
private static final String[] KEYPAD = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
public List<String> letterCombinations(String digits) {
if (digits == null || digits.isEmpty()) {
return List.of();
}
return letterCombinations(digits, 0).collect(Collectors.toList());
}
private Stream<String> letterCombinations(String digits, int index) {
if (index == digits.length()) {
return Stream.of("");
}
String letters = KEYPAD[digits.charAt(index) - '0'];
return letters.chars()
.mapToObj(c -> (char) c)
.flatMap(letter -> letterCombinations(digits, index + 1).map(combination -> letter + combination));
}
}
解释
方法:
这个题解使用回溯算法来解决电话号码的字母组合问题。首先,定义了一个字典 m,将数字映射到对应的字母。然后定义一个辅助函数 backtrack,它接受一个路径参数 path。在函数中,如果 path 的长度等于 digits 的长度,说明找到了一个完整的字母组合,将其加入答案列表 ans 中。否则,根据当前 path 的长度,从 digits 中取出对应的数字,并获取该数字对应的字母选择。遍历这些字母选择,将每个字母加入 path,递归调用 backtrack,然后在回溯时将该字母从 path 中移除。最后,在主函数中调用 backtrack([]),并返回答案列表 ans。
时间复杂度:
O(m^n * n)
空间复杂度:
O(m^n * n)
代码细节讲解
🦆
在回溯算法中,为什么在发现`path`的长度与`digits`的长度相等时,即认为找到了一个有效的字母组合?
▷🦆
在`backtrack`函数中,为什么选择在递归后移除`path`中最后一个元素(即执行`path.pop()`)?这与回溯算法的哪个特性相关?
▷🦆
字典`m`映射了数字到字母的关系,这种映射在算法中起到了什么作用?
▷相关问题
括号生成
数字 n
代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
示例 1:
输入:n = 3 输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:
输入:n = 1 输出:["()"]
提示:
1 <= n <= 8
组合总和
给你一个 无重复元素 的整数数组 candidates
和一个目标整数 target
,找出 candidates
中可以使数字和为目标数 target
的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates
中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target
的不同组合数少于 150
个。
示例 1:
输入:candidates =[2,3,6,7],
target =7
输出:[[2,2,3],[7]] 解释: 2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。 7 也是一个候选, 7 = 7 。 仅有这两种组合。
示例 2:
输入: candidates = [2,3,5],
target = 8
输出: [[2,2,2,2],[2,3,3],[3,5]]
示例 3:
输入: candidates = [2],
target = 1
输出: []
提示:
1 <= candidates.length <= 30
2 <= candidates[i] <= 40
candidates
的所有元素 互不相同1 <= target <= 40
二进制手表
二进制手表顶部有 4 个 LED 代表 小时(0-11),底部的 6 个 LED 代表 分钟(0-59)。每个 LED 代表一个 0 或 1,最低位在右侧。
- 例如,下面的二进制手表读取
"4:51"
。
给你一个整数 turnedOn
,表示当前亮着的 LED 的数量,返回二进制手表可以表示的所有可能时间。你可以 按任意顺序 返回答案。
小时不会以零开头:
- 例如,
"01:00"
是无效的时间,正确的写法应该是"1:00"
。
分钟必须由两位数组成,可能会以零开头:
- 例如,
"10:2"
是无效的时间,正确的写法应该是"10:02"
。
示例 1:
输入:turnedOn = 1 输出:["0:01","0:02","0:04","0:08","0:16","0:32","1:00","2:00","4:00","8:00"]
示例 2:
输入:turnedOn = 9 输出:[]
提示:
0 <= turnedOn <= 10