题目:组合
问题描述:给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
解题思路
- 回溯法:使用回溯法生成所有可能的组合。
- 递归构建组合:
- 从1到n中选择一个数作为组合的第一个数,然后递归地从剩余的数中选择k-1个数。
- 剪枝优化:
- 在递归过程中,通过计算剩余可选的数的数量来提前终止不必要的递归,从而减少计算量。
- 路径记录:
- 使用一个列表
path来记录当前的组合路径。
- 结果收集:
- 当
path的长度等于 k 时,将其添加到结果列表result中。
代码:
class Solution {
List<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combine(int n, int k) {
backtreeing(n,k,1);
return result;
}
public void backtreeing(int n, int k,int startindex) {
if(path.size() == k){
result.add(new ArrayList<>(path));
return;
}
for(int i = startindex;i<=n;i++){
path.add(i);
backtreeing(n,k,i+1);
path.removeLast();
}
}
}
class Solution {
List<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combine(int n, int k) {
backtreeing(n,k,1);
return result;
}
public void backtreeing(int n, int k,int startindex) {
if(path.size() == k){
result.add(new ArrayList<>(path));
return;
}
for(int i = startindex;i<=n-(k-path.size())+1;i++){
path.add(i);
backtreeing(n,k,i+1);
path.removeLast();
}
}
}
216. 组合总和 III
题目描述
找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。
说明:
- 所有数字都是正整数。
- 解集不能包含重复的组合。
解题思路
这道题是一个典型的回溯问题。我们需要从数字 1 到 9 中选择 k 个数字,并确保它们的和为 n。通过回溯的方式,我们可以探索所有的组合。
关键点:
- 递归回溯:每次选择一个数字,并将其添加到路径中,再继续选择下一个数字。回溯时要恢复状态。
- 限制条件:
- 当前组合的大小不能超过
k。 - 每次选择的数字不能重复,并且必须从当前位置的下一个数字开始选择。
- 如果当前路径的和为
n且路径大小为k,则记录该路径。
- 当前组合的大小不能超过
步骤:
- 递归调用:我们从
1开始递归,每次选择一个数字加入路径并继续递归。 - 回溯:当递归到一个路径大小为
k时,检查路径和是否为n。如果是,加入结果列表。 - 优化剪枝:为了避免不必要的递归,递归中的
startIndex会根据剩余的数字个数进行调整。具体来说,在每一层递归中,我们可以减少剩余选择的数字数量。
代码实现
class Solution {
private List<List<Integer>> result = new ArrayList<>();
private LinkedList<Integer> path = new LinkedList<Integer>();
public List<List<Integer>> combinationSum3(int k, int n) {
treebuild(k,n,0,1);
return result;
}
public void treebuild(int k, int n,int sum,int startindex) {
if(path.size()==k){
if(sum==n){
result.add(new ArrayList<>(path));
}
return;
}
for(int i=startindex;i<10;i++){
path.add(i);
sum=sum+i;
treebuild(k,n,sum,i+1);
sum=sum-i;
path.removeLast();
}
}
}
class Solution {
private List<List<Integer>> result = new ArrayList<>();
private LinkedList<Integer> path = new LinkedList<Integer>();
public List<List<Integer>> combinationSum3(int k, int n) {
treebuild(k,n,0,1);
return result;
}
public void treebuild(int k, int n,int sum,int startindex) {
if(path.size()==k){
if(sum==n){
result.add(new ArrayList<>(path));
}
return;
}
for(int i=startindex;i<10-(k-path.size())+1;i++){
path.add(i);
sum=sum+i;
treebuild(k,n,sum,i+1);
sum=sum-i;
path.removeLast();
}
}
}
17. 电话号码的字母组合
题目描述
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母
解题思路
这道题是一个典型的回溯问题。我们需要通过递归遍历每个数字对应的字母,然后生成所有可能的字母组合。
关键点:
- 数字到字母的映射:每个数字(2-9)都对应一组字母,我们可以用数组或者字典来存储这种映射。
- 回溯法:我们可以使用回溯法来生成所有可能的组合。每次递归时,选择当前数字对应的字母之一,然后进入下一个数字的递归调用。
- 字符串拼接:用
StringBuilder来拼接每次的选择,避免频繁创建新的字符串。 - 终止条件:当递归到达数字字符串的末尾时,表示一个完整的组合已经生成,将其添加到结果列表中。
步骤:
- 递归遍历:从数字字符串的第一个字符开始,遍历所有可能的字母,递归调用下一层。
- 回溯:每当递归进入下一层时,我们会选择一个字母,递归回来后,删除上次选择的字母,继续选择下一个字母。
代码实现
class Solution {
private String[] numString = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
List<String> list = new ArrayList<>();
StringBuilder path = new StringBuilder();
public List<String> letterCombinations(String digits) {
if(digits==null || digits.length()==0){
return list;
}
treebuilding(digits,0);
return list;
}
public void treebuilding(String digits,int startindex) {
if(startindex==digits.length()){
list.add(path.toString());
return;
}
String str = numString[digits.charAt(startindex)-'0'];
for(int i = 0;i<str.length();i++){
path.append(str.charAt(i));
treebuilding(digits,startindex+1);
path.deleteCharAt(path.length()-1);
}
}
}
993

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



