Skip to content

Commit

Permalink
feat: implementation of find kth element in array (TheAlgorithms#472) (
Browse files Browse the repository at this point in the history
…TheAlgorithms#473)

* feat: implementation of find kth element in array (TheAlgorithms#472)

* feat: implementation of find kth element in array

* feat: implementation of find kth element in array

* Updated Documentation in README.md

Co-authored-by: github-action <${GITHUB_ACTOR}@users.noreply.github.com>
Co-authored-by: Rak Laptudirm <[email protected]>
  • Loading branch information
3 people authored Mar 11, 2022
1 parent 4f29592 commit b875ba7
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 11 deletions.
21 changes: 12 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -545,8 +545,10 @@ Read our [Contribution Guidelines](CONTRIBUTING.md) before you contribute.
##### Functions:

1. [`Abs`](./math/abs.go#L11): Abs returns absolute value
2. [`IsPowOfTwoUseLog`](./math/checkisnumberpoweroftwo.go#L10): IsPowOfTwoUseLog This function checks if a number is a power of two using the logarithm. The limiting degree can be from 0 to 63. See alternatives in the binary package.
3. [`Phi`](./math/eulertotient.go#L5): Phi is the Euler totient function. This function computes the number of numbers less then n that are coprime with n.
2. [`FindKthMax`](./math/kthnumber.go#L11): FindKthMax returns the kth large element given an integer slice with nil `error` if found and returns -1 with `error` `search.ErrNotFound` if not found. NOTE: The `nums` slice gets mutated in the process.
3. [`FindKthMin`](./math/kthnumber.go#L19): FindKthMin returns kth small element given an integer slice with nil `error` if found and returns -1 with `error` `search.ErrNotFound` if not found. NOTE: The `nums` slice gets mutated in the process.
4. [`IsPowOfTwoUseLog`](./math/checkisnumberpoweroftwo.go#L10): IsPowOfTwoUseLog This function checks if a number is a power of two using the logarithm. The limiting degree can be from 0 to 63. See alternatives in the binary package.
5. [`Phi`](./math/eulertotient.go#L5): Phi is the Euler totient function. This function computes the number of numbers less then n that are coprime with n.

---
</details><details>
Expand Down Expand Up @@ -861,13 +863,14 @@ Read our [Contribution Guidelines](CONTRIBUTING.md) before you contribute.
6. [`InsertionSort`](./sort/insertionsort.go#L3): No description provided.
7. [`MergeIter`](./sort/mergesort.go#L51): No description provided.
8. [`Mergesort`](./sort/mergesort.go#L37): Mergesort Perform mergesort on a slice of ints
9. [`Pigeonhole`](./sort/pigeonholesort.go#L12): Pigeonhole sorts a slice using pigeonhole sorting algorithm.
10. [`QuickSort`](./sort/quicksort.go#L37): QuickSort Sorts the entire array
11. [`QuickSortRange`](./sort/quicksort.go#L24): QuickSortRange Sorts the specified range within the array
12. [`RadixSort`](./sort/radixsort.go#L35): No description provided.
13. [`SelectionSort`](./sort/selectionsort.go#L3): No description provided.
14. [`ShellSort`](./sort/shellsort.go#L3): No description provided.
15. [`SimpleSort`](./sort/simplesort.go#L11): No description provided.
9. [`Partition`](./sort/quicksort.go#L10): No description provided.
10. [`Pigeonhole`](./sort/pigeonholesort.go#L12): Pigeonhole sorts a slice using pigeonhole sorting algorithm.
11. [`QuickSort`](./sort/quicksort.go#L37): QuickSort Sorts the entire array
12. [`QuickSortRange`](./sort/quicksort.go#L24): QuickSortRange Sorts the specified range within the array
13. [`RadixSort`](./sort/radixsort.go#L35): No description provided.
14. [`SelectionSort`](./sort/selectionsort.go#L3): No description provided.
15. [`ShellSort`](./sort/shellsort.go#L3): No description provided.
16. [`SimpleSort`](./sort/simplesort.go#L11): No description provided.

---
##### Types
Expand Down
43 changes: 43 additions & 0 deletions math/kthnumber.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package math

import (
"github.com/TheAlgorithms/Go/search"
"github.com/TheAlgorithms/Go/sort"
)

// FindKthMax returns the kth large element given an integer slice
// with nil `error` if found and returns -1 with `error` `search.ErrNotFound`
// if not found. NOTE: The `nums` slice gets mutated in the process.
func FindKthMax(nums []int, k int) (int, error) {
index := len(nums) - k
return kthNumber(nums, index)
}

// FindKthMin returns kth small element given an integer slice
// with nil `error` if found and returns -1 with `error` `search.ErrNotFound`
// if not found. NOTE: The `nums` slice gets mutated in the process.
func FindKthMin(nums []int, k int) (int, error) {
index := k - 1
return kthNumber(nums, index)
}

// kthNumber use the selection algorithm (based on the partition method - the same one as used in quicksort).
func kthNumber(nums []int, k int) (int, error) {
if k < 0 || k >= len(nums) {
return -1, search.ErrNotFound
}
start := 0
end := len(nums) - 1
for start <= end {
pivot := sort.Partition(nums, start, end)
if k == pivot {
return nums[pivot], nil
}
if k > pivot {
start = pivot + 1
continue
}
end = pivot - 1
}
return -1, search.ErrNotFound
}
104 changes: 104 additions & 0 deletions math/kthnumber_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package math

import (
"github.com/TheAlgorithms/Go/search"
"testing"
)

func TestFindKthMax(t *testing.T) {
sortTests := []struct {
input []int
k int
expected int
err error
name string
}{
{
input: []int{6, 7, 0, -1, 10, 70, 8, 22, 3, 9},
k: 3,
expected: 10,
name: "3th largest number",
},
{
input: []int{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
k: 3,
expected: -1,
name: "3th largest number",
},
{
input: []int{-1, -1, -1, -1, -1, -1},
k: 7,
expected: -1,
err: search.ErrNotFound,
name: "This should be an error",
},
{
input: []int{},
k: 1,
expected: -1,
err: search.ErrNotFound,
name: "This should be an error",
},
}
for _, test := range sortTests {
t.Run(test.name, func(t *testing.T) {
actual, err := FindKthMax(test.input, test.k)
if err != test.err {
t.Errorf("name:%v FindKthMax() = %v, want err: %v", test.name, err, test.err)
}
if actual != test.expected {
t.Errorf("test %s failed", test.name)
t.Errorf("actual %v expected %v", actual, test.expected)
}
})
}
}

func TestFindKthMin(t *testing.T) {
sortTests := []struct {
input []int
k int
expected int
err error
name string
}{
{
input: []int{6, 7, 0, -1, 10, 70, 8, 22, 3, 9},
k: 3,
expected: 3,
name: "3th smallest number",
},
{
input: []int{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
k: 3,
expected: -1,
name: "3th smallest number",
},
{
input: []int{-1, -1, -1, -1, -1, -1},
k: 7,
expected: -1,
err: search.ErrNotFound,
name: "This should be an error",
},
{
input: []int{},
k: 1,
expected: -1,
err: search.ErrNotFound,
name: "This should be an error",
},
}
for _, test := range sortTests {
t.Run(test.name, func(t *testing.T) {
actual, err := FindKthMin(test.input, test.k)
if err != test.err {
t.Errorf("name:%v FindKthMin() = %v, want err: %v", test.name, err, test.err)
}
if actual != test.expected {
t.Errorf("test %s failed", test.name)
t.Errorf("actual %v expected %v", actual, test.expected)
}
})
}
}
4 changes: 2 additions & 2 deletions sort/quicksort.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

package sort

func partition(arr []int, low, high int) int {
func Partition(arr []int, low, high int) int {
index := low - 1
pivotElement := arr[high]
for i := low; i < high; i++ {
Expand All @@ -27,7 +27,7 @@ func QuickSortRange(arr []int, low, high int) {
}

if low < high {
pivot := partition(arr, low, high)
pivot := Partition(arr, low, high)
QuickSortRange(arr, low, pivot-1)
QuickSortRange(arr, pivot+1, high)
}
Expand Down

0 comments on commit b875ba7

Please sign in to comment.