详细见:leetcode.com/problems/subsets-ii
Java Solution: github
package leetcode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/*
* Given a collection of integers that might contain duplicates, nums,
* return all possible subsets.
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],
[]
]
*/
public class P090_SubsetsII {
public static void main(String[] args) {
int[] nums = null;
nums = new int[] {1, 1, 2, 2, 3, 3};
List<List<Integer>> ans = new Solution().subsetsWithDup(nums);
Iterator<List<Integer>> it = ans.iterator();
while (it.hasNext()) {
tools.Utils.B_打印List_Integer_OneLine(it.next());
}
}
/*
* AC
* 无论何时,都需要耐心分析边界问题。
* 3 ms
*/
static class Solution {
List<List<Integer>> ans = new LinkedList<>();
int[] first_same, last_same, record, nums;
public List<List<Integer>> subsetsWithDup(int[] nums) {
ans.add(new LinkedList<Integer>());
if (nums == null || nums.length == 0) {
return ans;
}
Arrays.sort(nums);
this.nums = nums;
first_same = new int[nums.length];
last_same = new int[nums.length];
record = new int[nums.length];
for (int i = 0; i != nums.length; i ++) {
if (0 == i || nums[i - 1] != nums[i]) {
first_same[i] = i;
} else {
first_same[i] = first_same[i - 1];
}
}
for (int i = nums.length - 1; i > - 1; i --) {
if (i == nums.length - 1 || nums[i] != nums[i + 1]) {
last_same[i] = i;
} else {
last_same[i] = last_same[i + 1];
}
}
// tools.Utils.printArray(first_same, 10);
// tools.Utils.printArray(last_same, 10);
for (int len = 1; len <= nums.length; len ++) {
search(len, 0, 0);
}
return ans;
}
private void search(int len, int len_now, int sti) {
if (len_now == len) {
List<Integer> temp = new ArrayList<Integer>(len);
for (int i = 0; i != len; i ++) {
temp.add(record[i]);
}
ans.add(temp);
return;
}
for (int i = sti; i < nums.length; i ++) {
if (first_same[i] == last_same[i]) {
record[len_now] = nums[i];
search(len, len_now + 1, i + 1);
} else {
int count_same = last_same[i] - first_same[i];
for (int same_now = 0; same_now <= count_same; same_now ++) {
if (len_now + same_now >= len) {
break;
}
// if (same_now != 0) {
record[len_now + same_now] = nums[i];
// }
search(len, len_now + same_now + 1, last_same[i] + 1);
}
i += count_same;
}
}
}
}
}
C Solution: github
/*
url: leetcode.com/problems/subsets-ii
AC 3ms 70.59%
*/
#include <stdio.h>
#include <stdlib.h>
typedef int* T;
typedef struct al sal;
typedef struct al * pal;
struct al {
int capacity;
int size;
T* arr;
};
pal al_init(int capacity) {
pal l = (pal) malloc(sizeof(sal));
if (capacity < 1) return NULL;
l->arr = (T*) malloc(sizeof(T) * capacity);
l->capacity = capacity;
l->size = 0;
return l;
}
void al_expand_capacity(pal l) {
T* new_arr = (T*) malloc(sizeof(T) * (l->capacity * 2 + 1));
int i = 0;
for (i = 0; i < l->capacity; i ++)
new_arr[i] = l->arr[i];
free(l->arr);
l->arr = new_arr;
l->capacity = l->capacity * 2 + 1;
}
void al_add_last(pal l, T v) {
if (l->capacity == l->size) al_expand_capacity(l);
l->arr[l->size] = v;
l->size ++;
}
T* al_convert_to_array_free_l(pal l) {
T* arr = l->arr;
free(l);
return arr;
}
void al_free(pal l) {
int i = 0;
for (i = 0; i < l->size; i ++)
free(l->arr[i]);
free(l->arr);
free(l);
}
int partition(int* n, int i, int j) {
int s = n[i];
while (i < j) {
while (i < j && n[j] >= s) j --;
n[i] = n[j];
while (i < j && n[i] <= s) i ++;
n[j] = n[i];
}
n[i] = s;
return i;
}
void quick_sort(int* n, int i, int j) {
int p = 0;
if (i+1 < j) {
p = partition(n, i, j-1);
quick_sort(n, i, p);
quick_sort(n, p+1, j);
}
}
int* arr_copy(int* s, int sn) {
int* t = (int*) malloc(sizeof(int) * sn);
int i = 0;
for (i = 0; i < sn; i ++) {
t[i] = s[i];
}
return t;
}
int* arr_int(int val) {
int* t = (int*) malloc(sizeof(int));
t[0] = val;
return t;
}
void search(pal l, pal ln, int* n, int ni, int nn, int* s, int si, int sn, int sign) {
int i = 0;
if (si == sn && ni == nn) {
al_add_last(l, arr_copy(s, sn));
al_add_last(ln, arr_int(sn));
return;
}
if (ni >= nn || si > sn) return;
if (! (sign && ni != 0 && n[ni-1] == n[ni])) {
search(l, ln, n, ni+1, nn, s, si, sn, 0);
}
if (si < sn) s[si] = n[ni];
search(l, ln, n, ni+1, nn, s, si+1, sn, 1);
}
int** subsetsWithDup(int* n, int nn, int** cn, int* rn) {
pal l = NULL, ln = NULL;
int ni = 0, *s = NULL, si = 0;
if (n == NULL || nn < 1) return NULL;
quick_sort(n, 0, nn);
l = al_init(16);
ln = al_init(16);
s = (int*) malloc(sizeof(int) * nn);
for (ni = 0; ni <= nn; ni ++) {
search(l, ln, n, 0, nn, s, 0, ni, 0);
}
*rn = l->size;
*cn = (int*) malloc(sizeof(int) * *rn);
for (si = 0; si < *rn; si ++)
(*cn)[si] = ln->arr[si][0];
al_free(ln);
return al_convert_to_array_free_l(l);
}
int main() {
int n[] = {1,4,3,5,4,4,7,7,8,0};
int nn = 2;
int rn = 0;
int* cn = NULL;
int** a = subsetsWithDup(n, nn, &cn, &rn);
int i = 0, j = 0;
for (i = 0; i < rn; i ++) {
for (j = 0; j < cn[i]; j ++) {
printf("%d ", a[i][j]);
}
printf("\r\n");
free(a[i]);
}
free(a);
}
Python Solution: github
#coding=utf-8
'''
url: leetcode.com/problems/subsets-ii
@author: zxwtry
@email: zxwtry@qq.com
@date: 2017年4月22日
@details: Solution: 65ms 71.66%
'''
class Solution(object):
def search(self, n, ni, nn, r, ri, rn, iu, a):
if ni == nn and ri == rn:
a.append(list(r))
if ni >= nn or ri > rn: return
if not (ni != 0 and iu and n[ni-1]==n[ni]):
self.search(n, ni+1, nn, r, ri, rn, False, a)
if ri < rn: r[ri] = n[ni]
self.search(n, ni+1, nn, r, ri+1, rn, True, a)
def subsetsWithDup(self, n):
"""
:type n: List[int]
:rtype: List[List[int]]
"""
nn = 0 if n == None else len(n)
if nn == 0: return []
n.sort(key=None, reverse=False)
a = []
for rn in range(nn+1):
r = [0]*rn
self.search(n, 0, nn, r, 0, rn, False, a)
return a
if __name__ == "__main__":
a = Solution().subsetsWithDup([1,2,2,2])
print(a)