仅做学习笔记之用。
题目:
给定一个仅包含数字 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']
的一个数字。
思路是这样的:
事先写好一个有着对应数字的字母表,就像图里那样,放在一个字符串数组中。(要注意数组前两个元素应当是空字符串,因为根据下标,数组的顺序是0,1,2,所以应该从第三个元素开始写。就照着图里那样,打过九键的人应该都明白)
然后用一个递归方法排列组合,这个方法会为每个数字添加可能的字母,并在每次递归的最后检查是否已经构建了一个完整的组合。如果是,就将其添加到结果列表中。这个过程会一直持续,直到所有可能的组合都被生成出来。
方法会在每次进入方法中先判断是否已经生成了一条完整的排列,如果是就直接返回。
然后根据当前数字,找到所有可能的字母组合。(比如题目示例1、3中那样),然后将它们添加到一个StringBuilder的中,记得返回时要toString。然后递归调用,每次传递的是新的StringBuilder和下一个目标数字对应的下标,(不过也没差,我们在数组中已经提前在开头翻个两个空串)
递归调用返回后,从StringBuilder中移除最后添加的字母,以便尝试其他可能的字母。这个过程称为“回溯”。
有关于回溯:
(以下内容来自于GPT)
回溯算法是一种解决问题的算法,它尝试分步解决一个问题。如果发现当前的步骤不能得到有效的解决方案,它将取消上一步或几步的计算,再尝试其他的可能的选项。回溯算法通常用在解决组合问题、划分问题、排列问题、子集问题等一类需要穷尽所有可能情况的场合。
回溯算法的核心是“试错”,即当探索到某一步时,发现这一步骤不可能得到最终的正确解答,就退回一步重新尝试其他选项,这个过程可能会递归地重复。
以下是回溯算法的一般步骤:
1. **选择**:从候选解中选择一个可能的解。在许多问题中,这一步涉及到对当前部分解的扩展。例如,在八皇后问题中,选择一个列放置一个皇后。
2. **约束**:检查到目前为止的解是否满足问题的约束。如果满足约束,就继续扩展;如果不满足,就放弃这个解。
3. **目标**:检查到目前为止的解是否满足目标条件。如果满足目标条件,就记录这个解,并继续尝试其他可能的解;如果不满足,就放弃这个解。
4. **回溯**:如果当前的候选解不能得到有效的解,或者已经尝试完所有可能的候选解,就回退到上一步,尝试其他的候选解。
回溯算法的关键在于如何设计“选择”和“约束”步骤,以及如何有效地存储和管理已经探索过的部分解,以避免重复计算。
回溯算法的优缺点:
**优点**:
- 能够找到问题的所有的解,适用于需要穷尽所有可能性的问题。
- 可以找到问题的最优解。
**缺点**:
- 效率较低,尤其是在解空间很大的时候。
- 需要消耗大量的内存来存储中间状态。
回溯算法的应用场景:
- 子集问题,如子集和问题。
- 排列和组合问题。
- 字符串匹配问题,如正则表达式匹配。
- 路径问题,如图的着色问题、旅行商问题(TSP)。
- 游戏问题,如八皇后问题、数独等。
回溯算法是一种非常强大且灵活的算法,适用于解决许多复杂的问题。然而,由于它的低效率和高内存消耗,通常需要结合剪枝等优化策略来提高效率。
代码如下:
public class Solution {
private final String[] keyboard = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
public List<String> letterCombinations(String digits) {
List<String> result = new ArrayList<>();
if (digits == null || digits.isEmpty()) {
return result;
}
create(result, new StringBuilder(), digits, 0);
return result;
}
private void create(List<String> result, StringBuilder current, String digits, int index) {
if (current.length() == digits.length()) {
result.add(current.toString());
return;
}
String letters = keyboard[digits.charAt(index) - '0'];
for (int i = 0; i < letters.length(); i++) {
current.append(letters.charAt(i));
create(result, current, digits, index + 1);
current.deleteCharAt(current.length() - 1);
}
}
}
(算法大佬英雄哪里出来曾曰:过——啦)
解决。