-
Notifications
You must be signed in to change notification settings - Fork 376
/
subsets_duplicates_test.go
88 lines (73 loc) · 2.17 KB
/
subsets_duplicates_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*
Problem:
- Given a set with duplicate elements, find all the distinct subsets.
Example:
- Input: [1 2]
Output: [[] [1] [2] [1 2]]
- Input: [1 2 5]
Output: [[] [1] [2] [1 2] [3] [1 3] [2 3] [1 2 3]]
Approach:
- Similar to the previous problem, but we do two more steps.
- First, sort the set so that duplicates are next to each other.
- Second, when we encounter a duplicate while iterating the set,
only create subsets from the subsets that added previously.
- Can use a two-pointer approach to update their start and end window
accordingly.
Cost:
- O(2^n) time, O(2^n) space since we would have a total of 2^n subsets.
*/
package gtci
import (
"sort"
"testing"
"github.com/hoanhan101/algo/common"
)
func TestFindSubsetsWithDuplicates(t *testing.T) {
tests := []struct {
in []int
expected [][]int
}{
{[]int{}, [][]int{{}}},
{[]int{1}, [][]int{{}, {1}}},
{[]int{1, 2}, [][]int{{}, {1}, {2}, {1, 2}}},
{[]int{1, 2, 2}, [][]int{{}, {1}, {2}, {1, 2}, {2, 2}, {1, 2, 2}}},
{[]int{2, 1, 2}, [][]int{{}, {1}, {2}, {1, 2}, {2, 2}, {1, 2, 2}}},
{[]int{2, 2, 1}, [][]int{{}, {1}, {2}, {1, 2}, {2, 2}, {1, 2, 2}}},
{[]int{1, 2, 3}, [][]int{{}, {1}, {2}, {1, 2}, {3}, {1, 3}, {2, 3}, {1, 2, 3}}},
{[]int{3, 2, 1}, [][]int{{}, {1}, {2}, {1, 2}, {3}, {1, 3}, {2, 3}, {1, 2, 3}}},
}
for _, tt := range tests {
common.Equal(
t,
tt.expected,
findSubsetsWithDuplicates(tt.in),
)
}
}
func findSubsetsWithDuplicates(nums []int) [][]int {
// sort the set in ascending order.
sort.Slice(nums, func(i, j int) bool {
return nums[i] < nums[j]
})
// start with an empty set.
subsets := [][]int{}
subsets = append(subsets, []int{})
start, end := 0, 0
// for each number in the set, add it to all existing sets.
for i := 0; i < len(nums); i++ {
// if the current item and the previous one are the same, update the
// start index accordingly so that we only create subset from the one
// that added in the previous step.
start = 0
if i > 0 && nums[i] == nums[i-1] {
start = end + 1
}
end = len(subsets) - 1
for j := start; j < end+1; j++ {
set := subsets[j]
set = append(set, nums[i])
subsets = append(subsets, set)
}
}
return subsets
}