Skip to content

Commit

Permalink
Merge 0c84a2c into bd446c1
Browse files Browse the repository at this point in the history
  • Loading branch information
vaskoz committed Jan 25, 2019
2 parents bd446c1 + 0c84a2c commit 96bc1f3
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,4 @@ problems from
* [Day 151](https://github.com/vaskoz/dailycodingproblem-go/issues/313)
* [Day 153](https://github.com/vaskoz/dailycodingproblem-go/issues/316)
* [Day 154](https://github.com/vaskoz/dailycodingproblem-go/issues/320)
* [Day 155](https://github.com/vaskoz/dailycodingproblem-go/issues/322)
75 changes: 75 additions & 0 deletions day155/problem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package day155

import (
"errors"
"sort"
)

var errNoMajority = errors.New("no majority exists")

// ErrNoMajority returns the same error returned when no majority exists.
func ErrNoMajority() error {
return errNoMajority
}

// MajorityElementMap returns the number that occurs over half the time.
// Runs in O(N) time and O(unique values) in space.
func MajorityElementMap(nums []int) (int, error) {
counts := make(map[int]int)
for _, v := range nums {
counts[v]++
}
threshold := len(nums) / 2
for k, v := range counts {
if v >= threshold {
return k, nil
}
}
return 0, errNoMajority
}

// MajorityElementSort returns the number that occurs over half the time.
// Runs in O(N log N) time and O(1) in space.
func MajorityElementSort(nums []int) (int, error) {
if len(nums) < 1 {
return 0, errNoMajority
}
nums = append([]int{}, nums...) // don't mutate the input.
sort.Ints(nums)
var maxVal, maxCount int
val := nums[0]
count := 1
for i := 1; i < len(nums); i++ {
if nums[i] == val {
count++
} else {
if count > maxCount {
maxCount = count
maxVal = val
}
val = nums[i]
count = 1
}
}
if count > maxCount {
return val, nil
}
return maxVal, nil
}

// MajorityBoyerMoore runs in O(N) time and O(1) space.
// Limitation: only works if there is definitely a majority value.
func MajorityBoyerMoore(nums []int) (int, error) {
var m, i int
for _, x := range nums {
if i == 0 {
m = x
i = 1
} else if m == x {
i++
} else {
i--
}
}
return m, nil
}
68 changes: 68 additions & 0 deletions day155/problem_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package day155

import "testing"

var testcases = []struct {
nums []int
majority int
err error
}{
{[]int{1, 2, 1, 1, 3, 1, 4, 0}, 1, nil},
{[]int{}, 0, ErrNoMajority()},
{[]int{4, 1, 2, 4, 1, 4, 1, 3, 4, 0, 4}, 4, nil},
{[]int{1, 2, 4, 1, 4, 1, 4, 3, 4, 0, 4}, 4, nil},
}

func TestMajorityElementMap(t *testing.T) {
t.Parallel()
for _, tc := range testcases {
if result, err := MajorityElementMap(tc.nums); err != tc.err || result != tc.majority {
t.Errorf("Expected (%v,%v) got (%v,%v)", tc.majority, tc.err, result, err)
}
}
}

func TestMajorityElementSort(t *testing.T) {
t.Parallel()
for _, tc := range testcases {
if result, err := MajorityElementSort(tc.nums); err != tc.err || result != tc.majority {
t.Errorf("Expected (%v,%v) got (%v,%v)", tc.majority, tc.err, result, err)
}
}
}

func TestMajorityBoyerMoore(t *testing.T) {
t.Parallel()
for _, tc := range testcases {
if tc.err != nil {
continue
}
if result, err := MajorityBoyerMoore(tc.nums); err != tc.err || result != tc.majority {
t.Errorf("Expected (%v,%v) got (%v,%v)", tc.majority, tc.err, result, err)
}
}
}

func BenchmarkMajorityElementMap(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, tc := range testcases {
MajorityElementMap(tc.nums)
}
}
}

func BenchmarkMajorityElementSort(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, tc := range testcases {
MajorityElementSort(tc.nums)
}
}
}

func BenchmarkMajorityBoyerMoore(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, tc := range testcases {
MajorityBoyerMoore(tc.nums)
}
}
}

0 comments on commit 96bc1f3

Please sign in to comment.