LeetCode90求集合的所有子集,集合是可以重複的
阿新 • • 發佈:2019-01-22
題目
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);
}
}
這個時間是最短的。