Skip to content

Commit aa31b3b

Browse files
authored
[Arrays & Hashing][Group Anagrams] - Implement solution for Leetcode 49 (#9)
1 parent df892d0 commit aa31b3b

File tree

4 files changed

+124
-7
lines changed

4 files changed

+124
-7
lines changed

1_arrays_and_hashing/3_two_sum/solution.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type Pair struct {
2222

2323
// Time complexity: O(n log n)
2424
// Space complexity: O(n)
25-
func TwoSumSorted(nums []int, target int) []int {
25+
func TwoSumSort(nums []int, target int) []int {
2626
pairs := make([]Pair, len(nums))
2727
for i, v := range nums {
2828
pairs[i] = Pair{val: v, idx: i}

1_arrays_and_hashing/3_two_sum/solution_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ func TestTwoSum(t *testing.T) {
2222
{"Brute - Duplicates", TwoSumBruteForce, []int{3, 3}, 6, []int{0, 1}},
2323

2424
// Sorting (Two Pointer)
25-
{"Sorted - Valid Pair", TwoSumSorted, []int{2, 7, 11, 15}, 9, []int{0, 1}},
26-
{"Sorted - No Pair", TwoSumSorted, []int{1, 2, 3}, 7, nil},
27-
{"Sorted - Empty", TwoSumSorted, []int{}, 0, nil},
28-
{"Sorted - Single Element", TwoSumSorted, []int{5}, 5, nil},
29-
{"Sorted - Negative Numbers", TwoSumSorted, []int{-3, 4, 3, 90}, 0, []int{0, 2}},
30-
{"Sorted - Duplicates", TwoSumSorted, []int{3, 3}, 6, []int{0, 1}},
25+
{"Sort - Valid Pair", TwoSumSort, []int{2, 7, 11, 15}, 9, []int{0, 1}},
26+
{"Sort - No Pair", TwoSumSort, []int{1, 2, 3}, 7, nil},
27+
{"Sort - Empty", TwoSumSort, []int{}, 0, nil},
28+
{"Sort - Single Element", TwoSumSort, []int{5}, 5, nil},
29+
{"Sort - Negative Numbers", TwoSumSort, []int{-3, 4, 3, 90}, 0, []int{0, 2}},
30+
{"Sort - Duplicates", TwoSumSort, []int{3, 3}, 6, []int{0, 1}},
3131

3232
// Map Two-Pass
3333
{"MapTwoPass - Valid Pair", TwoSumMapTwoPass, []int{2, 7, 11, 15}, 9, []int{0, 1}},
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package groupanagrams
2+
3+
import (
4+
"sort"
5+
"strings"
6+
)
7+
8+
// Time complexity: O(n * k log k), where n is the number of strings and k is the maximum length of a string.
9+
// Space complexity: O(n * k)
10+
func GroupAnagramsSort(strs []string) [][]string {
11+
if len(strs) == 0 {
12+
return [][]string{}
13+
}
14+
15+
anagramMap := make(map[string][]string)
16+
17+
// for _, str := range strs {
18+
// // Convert to a slice of runes to sort
19+
// runes := []rune(str)
20+
// sort.Slice(runes, func(i, j int) bool {
21+
// return runes[i] < runes[j]
22+
// })
23+
// key := string(runes)
24+
// anagramMap[key] = append(anagramMap[key], str)
25+
// }
26+
27+
for _, str := range strs {
28+
sChars := strings.Split(str, "")
29+
sort.Strings(sChars)
30+
sortedStr := strings.Join(sChars, "")
31+
32+
anagramMap[sortedStr] = append(anagramMap[sortedStr], str)
33+
}
34+
35+
result := make([][]string, 0, len(anagramMap)) // result := [][]string{}
36+
for _, group := range anagramMap {
37+
result = append(result, group)
38+
}
39+
return result
40+
}
41+
42+
// Time complexity: O(n * k)
43+
// Space complexity: O(n * k)
44+
func GroupAnagramsCount(strs []string) [][]string {
45+
if len(strs) == 0 {
46+
return [][]string{}
47+
}
48+
49+
anagramMap := make(map[[26]int][]string)
50+
51+
for _, str := range strs {
52+
var key [26]int
53+
for _, char := range str {
54+
if char >= 'a' && char <= 'z' {
55+
key[char-'a']++
56+
}
57+
}
58+
anagramMap[key] = append(anagramMap[key], str)
59+
}
60+
61+
result := make([][]string, 0, len(anagramMap))
62+
for _, group := range anagramMap {
63+
result = append(result, group)
64+
}
65+
return result
66+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package groupanagrams
2+
3+
import (
4+
"reflect"
5+
"sort"
6+
"strings"
7+
"testing"
8+
)
9+
10+
func sortGroups(groups [][]string) [][]string {
11+
for _, group := range groups {
12+
sort.Strings(group)
13+
}
14+
sort.Slice(groups, func(i, j int) bool {
15+
return strings.Join(groups[i], "") < strings.Join(groups[j], "")
16+
})
17+
return groups
18+
}
19+
20+
func TestGroupAnagrams(t *testing.T) {
21+
cases := []struct {
22+
name string
23+
fn func([]string) [][]string
24+
strs []string
25+
expected [][]string
26+
}{
27+
// GroupAnagramsSort
28+
{"Sort - Basic", GroupAnagramsSort, []string{"eat", "tea", "tan", "ate", "nat", "bat"}, [][]string{{"eat", "tea", "ate"}, {"tan", "nat"}, {"bat"}}},
29+
{"Sort - Empty", GroupAnagramsSort, []string{}, [][]string{}},
30+
{"Sort - Single Word", GroupAnagramsSort, []string{"abc"}, [][]string{{"abc"}}},
31+
{"Sort - All Same", GroupAnagramsSort, []string{"a", "a", "a"}, [][]string{{"a", "a", "a"}}},
32+
{"Sort - No Anagrams", GroupAnagramsSort, []string{"a", "b", "c"}, [][]string{{"a"}, {"b"}, {"c"}}},
33+
34+
// GroupAnagramsCount
35+
{"Count - Basic", GroupAnagramsCount, []string{"eat", "tea", "tan", "ate", "nat", "bat"}, [][]string{{"eat", "tea", "ate"}, {"tan", "nat"}, {"bat"}}},
36+
{"Count - Empty", GroupAnagramsCount, []string{}, [][]string{}},
37+
{"Count - Single Word", GroupAnagramsCount, []string{"abc"}, [][]string{{"abc"}}},
38+
{"Count - All Same", GroupAnagramsCount, []string{"a", "a", "a"}, [][]string{{"a", "a", "a"}}},
39+
{"Count - No Anagrams", GroupAnagramsCount, []string{"a", "b", "c"}, [][]string{{"a"}, {"b"}, {"c"}}},
40+
}
41+
42+
for _, c := range cases {
43+
t.Run(c.name, func(t *testing.T) {
44+
got := sortGroups(c.fn(c.strs))
45+
want := sortGroups(c.expected)
46+
if !reflect.DeepEqual(got, want) {
47+
t.Errorf("%s failed: expected %v, got %v", c.name, want, got)
48+
}
49+
})
50+
}
51+
}

0 commit comments

Comments
 (0)