216.组合总和Ⅲ
题目描述
找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:
只使用数字1到9
每个数字 最多使用一次
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
示例1:
输入:k=3,n=7k = 3, n = 7k=3,n=7
输出:[[1,2,4]][[1,2,4]][[1,2,4]]
示例2:
输入:k=3,n=9k = 3, n = 9k=3,n=9
输出:[[1,2,6],[1,3,5],[2,3,4]][[1,2,6], [1,3,5], [2,3,4]][[1,2,6],[1,3,5],[2,3,4]]
示例3:
输入:k=4,n=1k = 4, n = 1k=4,n=1
输出:[][][]
思路
组合问题首先想到的肯定是回溯法,但是如何使用就需要我们捕捉一些关键字了。
1、只使用数字1-9,说明回溯循环时只需遍历1-9即可
2、每个数字最多使用一次,说明在回溯循环时每次遍历需要从startindex开始
读懂关键字之后可以套入回溯法的常规套路:
1、回溯方法中的跳出条件为:数字达到了k个数的时候即可跳出,因为此时不符合条件则之后也不可能符合条件了,可以直接跳出。同时,若几个数字的和已经超出了所需条件,那么因为使用的是数字1-9,所以之后也不可能再减小,可以直接跳出。
2、答案列表添加的条件:数量上符合k个数字,同时几个数字的和符合条件,即可添加。
题解
class Solution {
LinkedList<Integer> path = new LinkedList<>();
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> combinationSum3(int k, int n) {
helper(n,k,1,0);
return result;
}
public void helper(int targetSum,int k,int startIndex,int sum){
if(sum > targetSum){
return ;
}
if(path.size() == k){
if(sum == targetSum){
result.add(new ArrayList<>(path));
}
return;
}
for(int i = startIndex;i<= 9-(k-path.size())+1;i++){
path.add(i);
sum += i;
helper(targetSum,k,i+1,sum);
path.removeLast();
sum -= i;
}
}
}
总结
本题是组合问题的一个应用,能够帮助熟悉回溯问题中组合问题的套路。
17.电话号码的字母组合
题目描述
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射与电话按键相同。注意 1 不对应任何字母。
示例1:
输入:digits="23"digits = "23"digits="23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]["ad","ae","af","bd","be","bf","cd","ce","cf"]["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例2:
输入:digits=""digits = ""digits=""
输出:[][][]
示例3:
输入:digits="2"digits = "2"digits="2"
输出:["a","b","c"]["a","b","c"]["a","b","c"]
思路
首先,能看出本题也是一个对回溯组合的应用,但本题存在一些难点:
1、从数字到字母的映射关系和遍历时一个数字对应了多个字母,需要考虑
2、本题中返回的数组是字符串类型,那么可以考虑使用char数组或StringBuilder来进行拼接
3、要求得到的结果是不区分顺序的,即,ab和ba表示的是同一个组合,所以在回溯的循环中还是要每次从startindex开始。
题解
class Solution {
List<String> list = new ArrayList<>();
public List<String> letterCombinations(String digits) {
if(digits == null || digits.length() == 0){
return list;
}
String[] numString = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
helper(digits,numString,0);
return list;
}
StringBuilder tmp = new StringBuilder();
public void helper(String digits,String[] numString,int num){
if(num == digits.length()){
list.add(tmp.toString());
return;
}
String string = numString[digits.charAt(num)-'0'];
for(int i=0;i<string.length();i++){
tmp.append(string.charAt(i));
helper(digits,numString,num+1);
tmp.deleteCharAt(tmp.length()-1);
}
}
}
总结
本题即使进行了拆解之后还是很难的,要注意在回溯的过程中生成的字符串要及时更新。
文章讲述了如何利用回溯法解决寻找数字组合的问题,例如找出所有和为n的k个数的组合,每个数字1到9最多使用一次。示例展示了不同输入下的输出结果,并解析了解题思路,包括回溯法的实现细节和跳出条件。此外,还介绍了电话号码字母组合的问题,同样运用回溯法处理多对一映射的组合问题。
58

被折叠的 条评论
为什么被折叠?



