#leetcode#
17.电话号码的字母组合
class Solution {
/**
* 生成电话号码对应的所有字母组合
* @param digits 输入的数字字符串(只包含2-9的数字)
* @return 所有可能的字母组合列表
*/
public List<String> letterCombinations(String digits) {
// 存储最终结果的列表
List<String> combinations = new ArrayList<String>();
// 边界条件:如果输入为空字符串,直接返回空列表
if (digits.length() == 0) {
return combinations;
}
// 建立数字到对应字母的映射表,模拟手机按键布局
Map<Character, String> phoneMap = new HashMap<Character, String>() {{
put('2', "abc");
put('3', "def");
put('4', "ghi");
put('5', "jkl");
put('6', "mno");
put('7', "pqrs");
put('8', "tuv");
put('9', "wxyz");
}};
// 调用回溯方法生成所有组合
// 参数:结果列表、映射表、输入数字、当前处理的索引、当前组合的字符串缓冲
backtrack(combinations, phoneMap, digits, 0, new StringBuffer());
return combinations;
}
/**
* 回溯算法核心:递归生成所有可能的字母组合
* @param combinations 存储结果的列表
* @param phoneMap 数字到字母的映射表
* @param digits 输入的数字字符串
* @param index 当前处理的数字索引(从0开始)
* @param combination 用于构建当前组合的字符串缓冲
*/
public void backtrack(List<String> combinations, Map<Character, String> phoneMap,
String digits, int index, StringBuffer combination) {
// 递归终止条件:当处理完所有数字时(索引等于数字长度)
if (index == digits.length()) {
// 将当前构建的组合转换为字符串,添加到结果列表
combinations.add(combination.toString());
} else {
// 获取当前索引对应的数字字符
char digit = digits.charAt(index);
// 从映射表中获取该数字对应的所有字母
String letters = phoneMap.get(digit);
// 字母的数量(用于循环遍历)
int lettersCount = letters.length();
// 遍历当前数字对应的所有字母
for (int i = 0; i < lettersCount; i++) {
// 将当前字母添加到组合中
combination.append(letters.charAt(i));
// 递归处理下一个数字(索引+1)
backtrack(combinations, phoneMap, digits, index + 1, combination);
// 回溯:移除最后添加的字母,尝试下一个可能的字母
combination.deleteCharAt(index);
}
}
}
}
39.组合总和
class Solution {
/**
* 找出所有候选数中可以使数字和为目标值的组合(候选数可重复使用)
* @param candidates 候选数字数组(无重复元素,均为正整数)
* @param target 目标和
* @return 所有满足条件的组合列表
*/
public List<List<Integer>> combinationSum(int[] candidates, int target) {
// 存储最终所有满足条件的组合
List<List<Integer>> ans = new ArrayList<List<Integer>>();
// 用于临时存储当前正在构建的组合
List<Integer> combine = new ArrayList<Integer>();
// 调用深度优先搜索函数,从索引0开始处理
dfs(candidates, target, ans, combine, 0);
return ans;
}
/**
* 深度优先搜索(回溯法)寻找所有符合条件的组合
* @param candidates 候选数字数组
* @param target 剩余需要达成的目标和(初始为target,逐步递减)
* @param ans 存储结果的组合列表
* @param combine 当前正在构建的组合
* @param idx 当前处理的候选数索引(用于避免重复组合,保证组合内元素顺序与数组一致)
*/
public void dfs(int[] candidates, int target, List<List<Integer>> ans, List<Integer> combine, int idx) {
// 递归终止条件1:已经遍历完所有候选数,直接返回
if (idx == candidates.length) {
return;
}
// 递归终止条件2:剩余目标和为0,说明当前组合满足条件
if (target == 0) {
// 将当前组合的副本添加到结果列表(避免后续修改影响已存储的组合)
ans.add(new ArrayList<Integer>(combine));
return;
}
// 情况1:不选择当前索引的候选数,直接递归处理下一个索引
dfs(candidates, target, ans, combine, idx + 1);
// 情况2:选择当前索引的候选数(前提是当前数不超过剩余目标和)
if (target - candidates[idx] >= 0) {
// 将当前候选数加入临时组合
combine.add(candidates[idx]);
// 递归处理:剩余目标和减去当前数,索引不变(允许重复使用当前数)
dfs(candidates, target - candidates[idx], ans, combine, idx);
// 回溯:移除最后添加的数,恢复到选择前的状态,以便尝试其他组合
combine.remove(combine.size() - 1);
}
}
}