题目链接:77. 组合
题目描述:给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
样例:
输入: n = 4, k = 2
输出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
思路:常规解法,递归+回溯,用一个下标startIndex表示当前搜索的起点,边搜便记录当前这条路径上的值,当搜到一轮答案之后回溯,删掉最后一个值,换条路径继续搜。
代码:
class Solution {
public void dfs(int n,int startIndex,List<Integer> list,List<List<Integer>> ans,int k){
if(k==list.size()){
List<Integer> list1=new ArrayList<>(list);
ans.add(list1);
return ;
}
for(int i=startIndex;i<=n;i++){
list.add(i);
dfs(n,i+1,list,ans,k);
list.remove(list.size()-1);
}
}
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> ans=new ArrayList<List<Integer>>();
if(n<k||k<=0){
return ans;
}
List<Integer> list=new ArrayList<>();
dfs(n,1,list,ans,k);
return ans;
}
}
相似题目:46. 全排列+47. 全排列 II
进一步,看39. 组合总和
题目描述:给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
样例:
输入:candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]
输入:candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
数据范围:
1 <= candidates.length <= 30
1 <= candidates[i] <= 200
candidate 中的每个元素都是独一无二的。
1 <= target <= 500
思路:和上面思路差不多,只是这里每个元素可以重复利用,因此搜索时候还是从当前节点开始搜。
代码:
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<Integer> list=new ArrayList<>();
List<List<Integer>> ans=new ArrayList<List<Integer>>();
dfs(candidates,0,list,ans,target);
return ans;
}
public void dfs(int nums[],int startIndex,List<Integer> list,List<List<Integer>> ans,int target){
if(target<0) return;
if(target==0){
ans.add(new ArrayList<>(list));
return ;
}
for(int i=startIndex;i<nums.length;i++){
list.add(nums[i]);
dfs(nums,i,list,ans,target-nums[i]);//可以重复利用每个元素,因此还是从当前位置开始搜
list.remove(list.size()-1);
}
}
}
题目链接:40. 组合总和 II
题目描述:给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
- 所有数字(包括目标数)都是正整数。
- 解集不能包含重复的组合。
样例:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
[1,2,2],
[5]
]
思路:一个数字只能用一次,做法就是先排个序,然后相邻两个相同的就直接continue以免重复记录答案。
class Solution {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
List<Integer> list=new ArrayList<>();
List<List<Integer>> ans=new ArrayList<List<Integer>>();
dfs(candidates,target,list,ans,0);
return ans;
}
public void dfs(int []nums,int target,List<Integer> list,List<List<Integer>> ans,int startIndex){
if(target<0) return;
if(target==0){
List<Integer> list1=new ArrayList<>(list);
ans.add(list1);
return;
}
for(int i=startIndex;i<nums.length;i++){
if(i>startIndex&&nums[i] == nums[i-1]) continue;//避免出现重复情况
list.add(nums[i]);
dfs(nums,target-nums[i],list,ans,i+1);
list.remove(list.size()-1);
}
}
}