Skip to content

Commit 44127b2

Browse files
authored
Exponential search (#247)
* feat: add exponential search * test: add test for exponential search * fix : prettier fix * fix: added parameters to iterative binary search * fix: prettier fix #2 * fix: modified the return on binary search and related tests
1 parent e6d916e commit 44127b2

File tree

4 files changed

+84
-23
lines changed

4 files changed

+84
-23
lines changed

search/binary_search.ts

+16-16
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,25 @@
88
*
99
* @param {number[]} array - sorted list of numbers
1010
* @param {number} target - target number to search for
11-
* @return {number} - index of the target number in the list, or -1 if not found
11+
* @return {number} - index of the target number in the list, or null if not found
1212
* @see [BinarySearch](https://www.geeksforgeeks.org/binary-search/)
1313
* @example binarySearch([1,2,3], 2) => 1
14-
* @example binarySearch([4,5,6], 2) => -1
14+
* @example binarySearch([4,5,6], 2) => null
1515
*/
1616

1717
export const binarySearchIterative = (
1818
array: number[],
19-
target: number
20-
): number => {
21-
if (array.length === 0) return -1
22-
23-
// declare pointers for the start, middle and end indices
24-
let start = 0,
25-
end = array.length - 1,
26-
middle = (start + end) >> 1
19+
target: number,
20+
start: number = 0,
21+
end: number = array.length - 1
22+
): number | null => {
23+
if (array.length === 0) return null
2724

2825
// ensure the target is within the bounds of the array
29-
if (target < array[start] || target > array[end]) return -1
26+
if (target < array[start] || target > array[end]) return null
27+
28+
// declare pointers for the middle index
29+
let middle = (start + end) >> 1
3030

3131
while (array[middle] !== target && start <= end) {
3232
// if the target is less than the middle value, move the end pointer to be middle -1 to narrow the search space
@@ -37,24 +37,24 @@ export const binarySearchIterative = (
3737
middle = (start + end) >> 1
3838
}
3939
// return the middle index if it is equal to target
40-
return array[middle] === target ? middle : -1
40+
return array[middle] === target ? middle : null
4141
}
4242

4343
export const binarySearchRecursive = (
4444
array: number[],
4545
target: number,
4646
start = 0,
4747
end = array.length - 1
48-
): number => {
49-
if (array.length === 0) return -1
48+
): number | null => {
49+
if (array.length === 0) return null
5050

5151
// ensure the target is within the bounds of the array
52-
if (target < array[start] || target > array[end]) return -1
52+
if (target < array[start] || target > array[end]) return null
5353

5454
const middle = (start + end) >> 1
5555

5656
if (array[middle] === target) return middle // target found
57-
if (start > end) return -1 // target not found
57+
if (start > end) return null // target not found
5858

5959
// if the target is less than the middle value, move the end pointer to be middle -1 to narrow the search space
6060
// otherwise, move the start pointer to be middle + 1

search/exponential_search.ts

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { binarySearchIterative } from './binary_search'
2+
3+
/**
4+
* @description Exponential search algorithm for a sorted array.
5+
*
6+
* The algorithm searches for a specific value in a sorted array by first finding a range
7+
* where the value may be present and then performing a binary search within that range.
8+
*
9+
* Compared with binary search, exponential search can be more convenient and advantageous
10+
* in cases where the element to be searched is closer to the beginning of the array,
11+
* thus avoiding several comparisons that would make the search more verbose.
12+
*
13+
* @param {number[]} array - sorted list of numbers
14+
* @param {number} x - target number to search for
15+
* @return {number | null} - index of the target number in the list, or null if not found
16+
* @see [ExponentialSearch](https://www.geeksforgeeks.org/exponential-search/)
17+
* @example exponentialSearch([1, 2, 3, 4, 5], 3) => 2
18+
* @example exponentialSearch([10, 20, 30, 40, 50], 35) => null
19+
*/
20+
21+
export const exponentialSearch = (
22+
array: number[],
23+
x: number
24+
): number | null => {
25+
const arrayLength = array.length
26+
if (arrayLength === 0) return null
27+
28+
if (array[0] === x) return 0
29+
30+
let i = 1
31+
while (i < arrayLength && array[i] <= x) {
32+
i = i * 2
33+
}
34+
35+
const start = Math.floor(i / 2)
36+
const end = Math.min(i, arrayLength - 1)
37+
const result = binarySearchIterative(array, x, start, end)
38+
39+
return result
40+
}

search/test/binary_search.test.ts

+9-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { binarySearchIterative, binarySearchRecursive } from '../binary_search'
22

33
describe('BinarySearch', () => {
44
const testArray: number[] = [1, 2, 3, 4]
5-
type FunctionsArray = { (array: number[], index: number): number }[]
5+
type FunctionsArray = { (array: number[], index: number): number | null }[]
66
const functions: FunctionsArray = [
77
binarySearchIterative,
88
binarySearchRecursive
@@ -12,14 +12,16 @@ describe('BinarySearch', () => {
1212
it('should be defined', () => {
1313
expect(func(testArray, 2)).toBeDefined()
1414
})
15-
it('should return a number', () => {
16-
expect(typeof func(testArray, 2)).toBe('number')
15+
it('should return a number or null', () => {
16+
expect(
17+
typeof func(testArray, 2) === 'number' || func(testArray, 2) === null
18+
).toBe(true)
1719
})
18-
it('should return -1 if the target is not found in the array', () => {
19-
expect(func(testArray, 5)).toBe(-1)
20+
it('should return null if the target is not found in the array', () => {
21+
expect(func(testArray, 5)).toBe(null)
2022
})
21-
it('should return -1 if there are no elements in the array', () => {
22-
expect(func([], 5)).toBe(-1)
23+
it('should return null if there are no elements in the array', () => {
24+
expect(func([], 5)).toBe(null)
2325
})
2426
it('should return the index of the target if it is found in the array', () => {
2527
expect(func(testArray, 2)).toBe(1)
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { exponentialSearch } from '../exponential_search'
2+
3+
describe('Exponential search', () => {
4+
test.each([
5+
[[1, 2, 3, 4, 5], 3, 2],
6+
[[10, 20, 30, 40, 50], 35, null],
7+
[[10, 20, 30, 40, 50], 10, 0],
8+
[[10, 20, 30, 40, 50], 50, 4],
9+
[[10, 20, 30, 40, 50], 60, null],
10+
[[], 10, null],
11+
[[1, 2, 3, 4, 5], 1, 0],
12+
[[1, 2, 3, 4, 5], 5, 4]
13+
])(
14+
'of %o, searching for %o, expected %i',
15+
(array: number[], target: number, expected: number | null) => {
16+
expect(exponentialSearch(array, target)).toBe(expected)
17+
}
18+
)
19+
})

0 commit comments

Comments
 (0)