leetcode90:Subsets II

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MMChinaMM/article/details/52326238

题目:求数组的各种组合,数组中可能存在重复的数字,但是求出来的所有组合中不能有重复的组合。

我的leetcode的所有代码已经放入github:https://github.com/gaohongbin/leetcode

代码:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
 * 题目:求一个数组nums的所有组合,nums中可能有重复的数字。但是求得的组合不能有相同的组合。
 * 例如:nums = [1,2,2]. 返回的结果为:
 * [
 *  [2],
 *  [1],
 *  [1,2,2],
 *  [2,2],
 *  [1,2],
 *  []
 * ]
 * @author hongbin.gao
 *
 */
public class Leetcode90 {
	public static void main(String[] args){
	 	int[] nums = {1,2,2};
	 	List<List<Integer>> list = subsetsWithDup(nums);
	 	System.out.println(list);
	}
	/**
	 * 方法一(被注释掉的这一大块是方法一):这种方法就是利用了剑指Offer里面的求字符组合的方法,先求出组合,最后再去掉重复的。
	 * @param nums
	 * @return
	 */
	
	/*public static List<List<Integer>> subsetsWithDup(int[] nums) {
	    List<List<Integer>> list = new ArrayList<List<Integer>>();
	    List<Integer> subList = new ArrayList<Integer>();
	    
	    if(nums == null || nums.length == 0)  //数组为空或者数组包含长度为0
	    	return list;
	    
	    Arrays.sort(nums); //对数组进行排序
	    for(int i=1;i<=nums.length;i++){
	    	subsetsWithDup_1(nums, 0, nums.length-1, i, list,subList);
	    } 
	    list.add(new ArrayList<Integer>()); //添加一个空的数组
	    return list;
	}
	
	public static void subsetsWithDup_1(int[] nums, int low, int high, int length, List<List<Integer>> list, List<Integer> subList){
		if(length == 0){
			boolean flag = false;
		
			if(list.contains(subList))
				flag = true;
			if(!flag){   //如果不存在,添加进去
				List<Integer> subList_1 = new ArrayList<Integer>();
				for(int i=0;i<subList.size();i++)
					subList_1.add(subList.get(i));
				list.add(subList_1);
				flag = false;
				return ;
			}
			else{  //存在的话,直接返回
				flag = false;
				return ;
			}
		}
		
		if(low == high+1)
			return ;
		
		subsetsWithDup_1(nums,low+1,high, length, list,subList); //不添加nums[low]
		
		subList.add(nums[low]);
		subsetsWithDup_1(nums,low+1,high, length-1, list,subList); //添加nums[low]
		subList.remove(subList.size()-1);
		
	}
*/
	/**
	 * 方法二:这个是在网上看到的,这个方法的思想:对于数组nums,我先求出以nums[0]开头的所有组合,在求出以nums[1]为开头的所有组合。
	 * nums[0]开头的组合可以看做nums[0]+{[2,2]数组的组合}
	 * nums[1]开头的组合可以看做nums[1]+{[2]数组的组合}
	 * 因为nums[1] == nums[2]所以nums[2]开头的组合包含在了nums[1]开头的组合里面了。
	 * @param nums
	 * @return
	 */
	
	public static List<List<Integer>> subsetsWithDup(int[] nums) {
		List<Integer> subList = new ArrayList<Integer>();
		List<List<Integer>> list = new ArrayList<List<Integer>>();
	    list.add(subList);
	    Arrays.sort(nums);
	    helper(nums,0,subList,list);
	    return list;
	    
	}
	
	public static void helper(int[] nums, int pos, List<Integer> subList, List<List<Integer>> list){
		if(pos == nums.length)
			return ;
		
		for(int i = pos;i<nums.length;i++){
			subList.add(nums[i]);  //先加入,和后面的remove对应,这样就能保证每次新的for循环,subList为空,就是依次以nums[0],nums[1],nums[2]为开头的组合
			List<Integer> subList_1 = new ArrayList<Integer>();
			for(int j=0;j<subList.size();j++)
				subList_1.add(subList.get(j));
			list.add(subList_1);
			helper(nums,i+1,subList,list); //对应的是上面注释里面{}里面的东西,因为传的是subList引用,所以可以实现+
			subList.remove(subList.size()-1);
			while(i<nums.length-1 && nums[i] == nums[i+1])  //因为nums[1] == nums[2]所以nums[2]开头的组合包含在了nums[1]开头的组合里面了。所以i++,指针直接往后
				i++;
		}
	}
}


猜你喜欢

转载自blog.csdn.net/MMChinaMM/article/details/52326238