leetcode【39,40,77,78,90,216】排列组合问题

组合问题:

题目中涉及到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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>