diff --git a/Search/BinarySearch.ts b/Search/BinarySearch.ts new file mode 100644 index 00000000..760a2c50 --- /dev/null +++ b/Search/BinarySearch.ts @@ -0,0 +1,58 @@ +/** + * @function binarySearch + * @description binary search algorithm (iterative & recursive implementations) for a sorted array. + * + * The algorithm searches for a specific value in a sorted array in logarithmic time. + * It repeatedly halves the portion of the list that could contain the item, + * until you've narrowed down the possible indices to just one. + * + * @param {number[]} array - sorted list of numbers + * @param {number} target - target number to search for + * @return {number} - index of the target number in the list, or -1 if not found + * @see [BinarySearch](https://www.geeksforgeeks.org/binary-search/) + * @example binarySearch([1,2,3], 2) => 1 + * @example binarySearch([4,5,6], 2) => -1 + */ + +export const binarySearchIterative = (array: number[], target: number): number => { + if (array.length === 0) return -1; + + // declare pointers for the start, middle and end indices + let start = 0, + end = array.length - 1, + middle = (start + end) >> 1; + + // ensure the target is within the bounds of the array + if (target < array[start] || target > array[end]) return -1; + + while (array[middle] !== target && start <= end) { + // if the target is less than the middle value, move the end pointer to be middle -1 to narrow the search space + // otherwise, move the start pointer to be middle + 1 + if (target < array[middle]) + end = middle - 1; + else + start = middle + 1; + // redeclare the middle index when the search window changes + middle = (start + end) >> 1; + } + // return the middle index if it is equal to target + return array[middle] === target ? middle : -1; +} + +export const binarySearchRecursive = (array: number[], target: number, start = 0, end = array.length - 1): number => { + if (array.length === 0) return -1; + + // ensure the target is within the bounds of the array + if (target < array[start] || target > array[end]) return -1; + + const middle = (start + end) >> 1; + + if (array[middle] === target) return middle; // target found + if (start > end) return -1; // target not found + + // if the target is less than the middle value, move the end pointer to be middle -1 to narrow the search space + // otherwise, move the start pointer to be middle + 1 + return target < array[middle] + ? binarySearchRecursive(array, target, start, middle - 1) + : binarySearchRecursive(array, target, middle + 1, end); +} \ No newline at end of file diff --git a/Search/test/BinarySearch.test.ts b/Search/test/BinarySearch.test.ts new file mode 100644 index 00000000..89f0b05c --- /dev/null +++ b/Search/test/BinarySearch.test.ts @@ -0,0 +1,34 @@ +import { binarySearchIterative, binarySearchRecursive } from "../BinarySearch"; + +describe("BinarySearch", () => { + const testArray: number[] = [1,2,3,4]; + type FunctionsArray = { (array: number[], index: number): number }[]; + const functions: FunctionsArray = [binarySearchIterative, binarySearchRecursive]; + + for (const func of functions) { + it("should be defined", () => { + expect(func(testArray, 2)).toBeDefined(); + }); + it("should return a number", () => { + expect(typeof func(testArray, 2)).toBe("number"); + }); + it("should return -1 if the target is not found in the array", () => { + expect(func(testArray, 5)).toBe(-1); + }); + it("should return -1 if there are no elements in the array", () => { + expect(func([], 5)).toBe(-1); + }); + it("should return the index of the target if it is found in the array", () => { + expect(func(testArray, 2)).toBe(1); + }); + it("should return a correct index of target when the array contains duplicate values", () => { + expect(func([1,2,2,3,3,3,4], 2)).toBe(1); + }); + it("should return the first index when the target is the first item in the array", () => { + expect(func(testArray, 1)).toBe(0); + }); + it("should return the last index when the target is the last item in the array", () => { + expect(func(testArray, 4)).toBe(3); + }); + } +}); \ No newline at end of file