组合问题:
题目中涉及到all possible sulutions时就要用到搜索算法,用深度优先搜索来解决。
leetcode 78.Subsets
题目描述
Given a set of distinct integers, nums, return all possible subsets (the power set).
Note: The solution set must not contain duplicate subsets.
Example:
Input: nums = [1,2,3]
Output:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
思路:
用递归的思想,从空集合开始,找到以nums中每个元素开始的所有可能的组合数。

实现:
public List<List<Integer>> subsets(int[] nums) {
//recursion:程序的一种实现方式,函数自己调用自己
List<List<Integer>> ret=new ArrayList<>();
if(nums==null){
return ret;
}
ArrayList<Integer> sub=new ArrayList<>();
//将所有以空集开头的集合加入到ret中
helper(ret,sub,nums,0);
return ret;
}
//递归的三要素之一:定义
//将以subset开头的所有的子集全部找到,并加入到ret中
private void helper(List<List<Integer>> ret,ArrayList<Integer> sub,int[] nums,int fromIndex){
//递归的三要素之二:极限小的状态
//if(XXX){ return }
//每当进入到一次新的递归,相等于从一个点进入到新的点,都需要将sub的结果加入到ret
//reference
ret.add(new ArrayList<>(sub));
//递归三要素之三:如何变为更小的状态
for(int i=fromIndex;i<nums.length;i++){
sub.add(nums[i]);
//将以nums[i]开头的数据加入到结果集中
helper(ret,sub,nums,i+1);
//以{1}开头的找到了
sub.remove(sub.size()-1);
}
}
leetcode 90. Subsets II
题目描述:
Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set).
Note: The solution set must not contain duplicate subsets.
Example:
Input: [1,2,2]
Output:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
思路:
和上面求集合的方法是一样的,只不过因为数组中包含重复的元素,所以在求组合数时,需要对重复的元素进行过滤。所以我们在逐个寻找以nums中某个元素开始的所有集合时,都判断一下当前元素是否和上一个元素一样,如果一样,就跳过。
实现:
public List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>> ret=new ArrayList<>();
if(nums==null||nums.length==0) return ret;
Arrays.sort(nums);
ArrayList<Integer> sub=new ArrayList<>();
fun(nums,ret,sub,0);
return ret;
}
private void fun(int[] nums,List<List<Integer>> ret,ArrayList<Integer> sub,int fromIndex){
ret.add(new ArrayList<>(sub));
for(int i=fromIndex;i<nums.length;i++){
if(i!=fromIndex&&nums[i]==nums[i-1]){
continue;
}
sub.add(nums[i]);
fun(nums,ret,sub,i+1);
sub.remove(sub.size()-1);
}
}
leetcode 77. Combinations
题目描述:
Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.
Example:
Input: n = 4, k = 2
Output:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
思路:
要求给出all possible combnations,所以我们也需要使用搜索算法来实现。可选的元素是1-n,每次选择一个元素后,都需要使用搜索算法(递归)将它与后面的元素做组合,集合中元素个数为k时停止搜索(递归截止的条件)。
因为我们的集合中必须存在k个元素,所以在从第一个元素开始逐个加入集合时,我们最多只能加到第n-k+1个元素,这样才保证集合中存在K个元素,比如加入[1,2,3,4,5,6,7,8,9,10],k=5,那我们集合开头的元素最多是6开头,这样保证集合至少有5个元素,[6,7,8,9,10],若我们选择7,则此时剩下的元素就不够5个了。
实现:
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> ret=new ArrayList<>();
ArrayList<Integer> sub=new ArrayList<>();
if(k>n||k<0||n<0){
return ret;
}
fun(n,k,1,ret,sub);
return ret;
}
private void fun(int n,int k,int indexFrom,List<List<Integer>> ret, ArrayList<Integer> sub){
if(k==0){
ret.add(new ArrayList<>(sub));//basecase,子集满了
return;
}
for(int i=indexFrom;i<=n-k+1;i++){
sub.add(i);//选择一个数
fun(n,k-1,i+1,ret,sub);//递归搜索
sub.remove(sub.size()-1);//不选择这个数
}
}
其他题目:
https://blog.csdn.net/orangefly0214/article/details/89959891

1724

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



