Skip to content

Commit

Permalink
add: median of medians algorithm solution for Miscellaneous
Browse files Browse the repository at this point in the history
  • Loading branch information
zhiwei-Feng committed Jun 24, 2021
1 parent 7db4f1b commit f4af3e1
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 0 deletions.
71 changes: 71 additions & 0 deletions Miscellaneous/median-of-medians.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package Miscellaneous

import (
"sort"
)

//
// coverage time complexity: O(n), worst O(n)
// space complexity: O(n)
//
func findKthSmallestNumberUsingMedianOfMedians(nums []int, k int) int {
if k > len(nums) {
return -1
}
return findPivotRecursive(nums, k, 0, len(nums)-1)
}

func findPivotRecursive(nums []int, k, start, end int) int {
p := partitionMom(nums, start, end)
if p == k-1 {
return nums[p]
}
if p > k-1 {
return findPivotRecursive(nums, k, start, p-1)
}
return findPivotRecursive(nums, k, p+1, end)
}

func partitionMom(nums []int, low, high int) int {
if low == high {
return low
}

median := medianOfMedians(nums, low, high)
// median as pivot
// swap high and median
for i := low; i < high; i++ {
if nums[i] == median {
nums[i], nums[high] = nums[high], nums[i]
break
}
}

pivot := nums[high]
i := low - 1
for j := low; j < high; j++ {
if nums[j] < pivot {
i++
nums[i], nums[j] = nums[j], nums[i]
}
}
nums[i+1], nums[high] = nums[high], nums[i+1]
return i + 1
}

func medianOfMedians(nums []int, low, high int) int {
n := high - low + 1
if n < 5 {
return nums[low]
}

numOfPartitions := n / 5
medians := make([]int, numOfPartitions)
for i := 0; i < numOfPartitions; i++ {
partStart := low + i*5
sort.Ints(nums[partStart : partStart+5])
medians[i] = nums[partStart+2]
}

return partitionMom(medians, 0, numOfPartitions-1)
}
27 changes: 27 additions & 0 deletions Miscellaneous/median-of-medians_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package Miscellaneous

import "testing"

func Test_findKthSmallestNumberUsingMedianOfMedians(t *testing.T) {
type args struct {
nums []int
k int
}
tests := []struct {
name string
args args
want int
}{
{"case1", args{[]int{1, 5, 12, 2, 11, 5}, 3}, 5},
{"case2", args{[]int{1, 5, 12, 2, 11, 5}, 4}, 5},
{"case3", args{[]int{5, 12, 11, -1, 12}, 3}, 11},
{"case4", args{[]int{5, 12, 11, -1, 12}, 6}, -1},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := findKthSmallestNumberUsingMedianOfMedians(tt.args.nums, tt.args.k); got != tt.want {
t.Errorf("findKthSmallestNumberUsingMedianOfMedians() = %v, want %v", got, tt.want)
}
})
}
}

0 comments on commit f4af3e1

Please sign in to comment.