LeetCode90求集合的所有子集,集合是可以重复的

原创 2018年04月17日 18:48:05

题目

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.

For example,
If nums = [1,2,2], a solution is:

[
  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]

因为可以重复,所以首先应该进行排序,Arrays.sort()函数,我以前没用过,现在知道有这样的一个函数了,但是我自己的写的冒泡排序比这个快,不知道为啥呀。

首先,看看我的两个逻辑,其实依赖map函数有点儿费时:

package leetcode;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class LC90SubSetsII {
	public static List<List<Integer>> subsetsWithDup(int[] nums) {
		List<List<Integer>> ret = new ArrayList<List<Integer>>();
		Map<String,Integer> map = new HashMap<String,Integer>();
		int len = nums.length;	
		if(len == 0){			
			return ret;		 
			
		}
		Arrays.sort(nums);//两种排序的对比
		
		/*for(int i = 0;i<len-1;i++){
			int min = nums[i];
			int t=i;
			for(int j=i+1;j<len;j++){
				if(nums[j]<min){
					min=nums[j];					
					t=j;
					
				}
				
			}
			if(t!=i){
				nums[t]=nums[i];
				nums[i]= min;
			}
			
			
		}*/
		
		for(int i=0;i<len;i++){
			int n = ret.size();
			for(int j=0;j<n;j++){
				List<Integer> temp = ret.get(j);
				List<Integer> list = new ArrayList<Integer>();
				String str = "";
				for(int k=0;k< temp.size();k++){
					list.add(temp.get(k));
					str=str+temp.get(k);
				}
				list.add(nums[i]);
				str=str+nums[i];
				if(map.containsKey(str)){
					continue;					
				}
				map.put(str, 1);
				ret.add(list);
				
			}
			List<Integer> list = new ArrayList<Integer>();
			if(map.containsKey(String.valueOf(nums[i]))){
				continue;					
			}
			map.put(String.valueOf(nums[i]), 1);
			list.add(nums[i]);
			ret.add(list);		
			
		}
		List<Integer> list = new ArrayList<Integer>();		
		ret.add(list);		

		return ret;		

	}
	
	public static void main(String[] args) {
		int[] nums={2,2,1,2};
		 List<List<Integer>> list = subsetsWithDup(nums);
		 for(int i =0;i<list.size();i++){
			 for(int j =0;j<list.get(i).size();j++){
				 System.out.print(list.get(i).get(j));
			 }
			 
			 System.out.println();
			 
		 }
		 
		 System.out.println(list.size());
		
	}

}

于是就又想了个办法,不用map的既然都排好序了,那么相同的必定都挨在一起了;对于相同的来说,只能增加包含这个数字的集合的基础上再次的增加这个数。于是具体代码如下:

package leetcode;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class LC90SubSetsIV {
	public static List<List<Integer>> subsetsWithDup(int[] nums) {
		List<List<Integer>> ret = new ArrayList<List<Integer>>();
		Map<String,Integer> map = new HashMap<String,Integer>();
		int len = nums.length;	
		if(len == 0){			
			return ret;		 
			
		}
		Arrays.sort(nums);
		
		List<List<Integer>> lastlist = new ArrayList<List<Integer>>();
		for(int i=0;i<len;i++){
			int n = ret.size();			
			if(i-1>0 && nums[i]==nums[i-1]){//相同的情况
				
				List<List<Integer>> lastdata = new ArrayList<List<Integer>>(lastlist);//但我估计这个费时就废在这段了
				int l=lastdata.size();
				lastlist.clear();//清空,为的就只保留增加的。
				for(int j=0;j<l;j++){
					List<Integer> temp = lastdata.get(j);
					List<Integer> list = new ArrayList<Integer>(temp);				
					list.add(nums[i]);
					ret.add(list);					
					lastlist.add(list);
					
				}			
			}else{
				lastlist.clear();
				for(int j=0;j<n;j++){
					List<Integer> temp = ret.get(j);
					List<Integer> list = new ArrayList<Integer>(temp);				
					list.add(nums[i]);
					ret.add(list);					
					lastlist.add(list);
					
				}
				List<Integer> list = new ArrayList<Integer>();
				if(map.containsKey(String.valueOf(nums[i]))){
					continue;					
				}
				map.put(String.valueOf(nums[i]), 1);
				list.add(nums[i]);
				ret.add(list);
				lastlist.add(list);
				
			}
			
				
			
		}
		List<Integer> list = new ArrayList<Integer>();		
		ret.add(list);		

		return ret;		

	}
	
	public static void main(String[] args) {
		int[] nums={2,2,1,3};
		 List<List<Integer>> list = subsetsWithDup(nums);
		 for(int i =0;i<list.size();i++){
			 for(int j =0;j<list.get(i).size();j++){
				 System.out.print(list.get(i).get(j));
			 }
			 
			 System.out.println();
			 
		 }
		 
		 System.out.println(list.size());
		
	}

}

下面就是递归的办法,这个时间是最短的,我暂时估计是因为地址指针的使用:

package leetcode;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class LC90SubSetsV {
	 public List<List<Integer>> subsetsWithDup(int[] nums) {
	        List<List<Integer>> result = new ArrayList<List<Integer>>();
	        if (nums == null || nums.length == 0) {
	            return result;
	        }
	        Arrays.sort(nums);
	        helper(result, new ArrayList<Integer>(), nums, 0);
	        return result;
	    }
	    
	    private void helper(List<List<Integer>> result, List<Integer> cur, int[] nums, int index) {
	        if (nums.length == index) {
	            result.add(new ArrayList<Integer>(cur));
	            return;
	        }
	        cur.add(nums[index]);//要了这个数字
	        helper(result, cur, nums, index + 1);
	        cur.remove(cur.size() - 1);//和不要这个数字
	        while (index + 1 < nums.length && nums[index + 1] == nums[index]) {
	            index++;
	        }
	        helper(result, cur, nums, index + 1);
	    }

}

这个时间是最短的。

java求无重复集合所有子集

在lintcode上遇到一道题,如下: 给定一个含不同整数的集合,返回其所有的子集 注意事项: 子集中的元素排列必须是非降序的,解集必须不包含重复的子集。...
  • yinglish_
  • yinglish_
  • 2016-09-10 23:32:04
  • 1538

求集合的所有子集(java实现)

代码: import java.io.File; import java.io.FileWriter; import java.io.IOException; /* *Created on 201...
  • caiandyong
  • caiandyong
  • 2015-01-31 22:08:20
  • 1295

【Java】通过位运算求一个集合的所有子集

Java没有自带的求一个集合的所有子集的方法,我们可以通过集合的子集规律来求。 一个集合的所有子集等于2^该集合的长度。比如{c,b,a}的长度为3,这个集合的子集就有8个。 这句话看起来很简单,...
  • yongh701
  • yongh701
  • 2016-12-12 15:50:35
  • 1731

求集合的所有子集的算法

求集合的所有子集的算法对于任意集合A,元素个数为n(空集n=0),其所有子集的个数为2^n个如集合A={a,b,c},其子集个数为8;对于任意一个元素,在每个子集中,要么存在,要么不存在,对应关系是:...
  • yzl20092856
  • yzl20092856
  • 2014-10-11 15:30:14
  • 2677

求一个集合子集的算法示例

  • 2014年06月14日 21:26
  • 464KB
  • 下载

递归求集合的所有子集的程序

#include #include using namespace std; //算法描述: //1、如果遍历完全集,打印出所有被标记为true的元素 //2、否则: //3、取第de...
  • woaifen3344
  • woaifen3344
  • 2012-04-25 13:01:48
  • 3491

回溯法 求集合全排列、子集

回溯法,参见之前的blog。 全排列: 全排列是将一组数按一定顺序进行排列,如果这组数有n个,那么全排列数为n!个。 从集合中依次选出每一个元素,作为排列的第一个元素,然后对剩余的元素进行全排列,如...
  • gfsfg8545
  • gfsfg8545
  • 2013-11-30 17:43:08
  • 4278

使用递归求出一个集合的所有子集

想一下,平时如果给你1,2,3,4四个数,让你写出它的所有子集,你会怎么做? 我想大部分人的思路是先写出子集中只含有一个元素的子集:1;2;3;4。然后考虑子集中含有两个元素的子集:1,2;1,3;...
  • nkuhjp
  • nkuhjp
  • 2016-09-21 21:05:46
  • 4399

求一个集合的所有子集问题

一个包含n个元素的集合,求它的所有子集。这种问题一般有两种思路,先说说第一种,递归。递归肯定要基于一个归纳法的思想。...
  • pony_maggie
  • pony_maggie
  • 2014-06-15 21:44:56
  • 18846

集合的所有子集的算法

转载自:http://blog.csdn.net/yzl20092856/article/details/39995085 求集合的所有子集的算法 对于任意集合A,元素个数为n(空集n=0),...
  • u010551600
  • u010551600
  • 2017-09-07 20:52:42
  • 557
收藏助手
不良信息举报
您举报文章:LeetCode90求集合的所有子集,集合是可以重复的
举报原因:
原因补充:

(最多只允许输入30个字)