Skip to content

Commit

Permalink
subsets with duplicates
Browse files Browse the repository at this point in the history
  • Loading branch information
hoanhan101 committed Apr 6, 2020
1 parent adb6d44 commit e2c761a
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 1 deletion.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 115+ Coding Interview Problems with Detailed Solutions
# 116+ Coding Interview Problems with Detailed Solutions

[![Build Status](https://travis-ci.com/hoanhan101/algo.svg?branch=master)](https://travis-ci.com/hoanhan101/algo)
[![Go Report Card](https://goreportcard.com/badge/github.com/hoanhan101/algo)
Expand Down Expand Up @@ -165,6 +165,7 @@ list here →](https://tinyletter.com/hoanhan)
- [Find the median of a number stream](gtci/median_number_stream_test.go)
- Subsets
- [Subsets](gtci/subsets_test.go)
- [Subsets with duplicates](gtci/subsets_duplicates_test.go)
- **[Grokking Dynamic Programming Patterns](https://www.educative.io/courses/grokking-dynamic-programming-patterns-for-coding-interviews)**
- Knapsack
- [0/1 Knapsack](gtci/knapsack_test.go)
Expand Down
88 changes: 88 additions & 0 deletions gtci/subsets_duplicates_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,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
}

0 comments on commit e2c761a

Please sign in to comment.