From 779f42b8ca0b9ed2a1027c00ee09c644035d5b20 Mon Sep 17 00:00:00 2001 From: NickMezacapa <89874146+NickMezacapa@users.noreply.github.com> Date: Wed, 5 Oct 2022 13:11:23 -0700 Subject: [PATCH 1/5] feat: add binary search algorithm --- Search/BinarySearch.ts | 58 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 Search/BinarySearch.ts diff --git a/Search/BinarySearch.ts b/Search/BinarySearch.ts new file mode 100644 index 00000000..7c9e1799 --- /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 = Math.floor((start + end) / 2); + + // 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 + target < array[middle] + ? end = middle - 1 + : start = middle + 1; + + // redeclare the middle index when the search window changes + middle = Math.floor((start + end) / 2); + } + // 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 = Math.floor((start + end) / 2); + + 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 From 978d822310ac1924c22925c99cf6a077914342e2 Mon Sep 17 00:00:00 2001 From: NickMezacapa <89874146+NickMezacapa@users.noreply.github.com> Date: Wed, 5 Oct 2022 13:11:55 -0700 Subject: [PATCH 2/5] test: add test for binary search algorithm --- Search/test/BinarySearch.test.ts | 34 ++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 Search/test/BinarySearch.test.ts 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 From 778d4923d59fe1e7398182f34d20bb7cfb6044c2 Mon Sep 17 00:00:00 2001 From: NickMezacapa <89874146+NickMezacapa@users.noreply.github.com> Date: Thu, 6 Oct 2022 12:53:48 -0700 Subject: [PATCH 3/5] rewrote ternary as if-else statement --- Search/BinarySearch.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Search/BinarySearch.ts b/Search/BinarySearch.ts index 7c9e1799..ae397883 100644 --- a/Search/BinarySearch.ts +++ b/Search/BinarySearch.ts @@ -28,9 +28,12 @@ export const binarySearchIterative = (array: number[], target: number): number = 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 - target < array[middle] - ? end = middle - 1 - : start = middle + 1; + if (target < array[middle]) { + end = middle - 1; + } + else { + start = middle + 1; + } // redeclare the middle index when the search window changes middle = Math.floor((start + end) / 2); From e2b97d92b2e5c70b00c46b894933ebe6ad92ac99 Mon Sep 17 00:00:00 2001 From: NickMezacapa <89874146+NickMezacapa@users.noreply.github.com> Date: Thu, 6 Oct 2022 13:02:30 -0700 Subject: [PATCH 4/5] changed instances of Math.floor to use a shift instead --- Search/BinarySearch.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Search/BinarySearch.ts b/Search/BinarySearch.ts index ae397883..1194b752 100644 --- a/Search/BinarySearch.ts +++ b/Search/BinarySearch.ts @@ -20,7 +20,7 @@ export const binarySearchIterative = (array: number[], target: number): number = // declare pointers for the start, middle and end indices let start = 0, end = array.length - 1, - middle = Math.floor((start + end) / 2); + middle = (start + end) >> 1; // ensure the target is within the bounds of the array if (target < array[start] || target > array[end]) return -1; @@ -34,9 +34,8 @@ export const binarySearchIterative = (array: number[], target: number): number = else { start = middle + 1; } - // redeclare the middle index when the search window changes - middle = Math.floor((start + end) / 2); + middle = (start + end) >> 1; } // return the middle index if it is equal to target return array[middle] === target ? middle : -1; @@ -48,7 +47,7 @@ export const binarySearchRecursive = (array: number[], target: number, start = 0 // ensure the target is within the bounds of the array if (target < array[start] || target > array[end]) return -1; - const middle = Math.floor((start + end) / 2); + const middle = (start + end) >> 1; if (array[middle] === target) return middle; // target found if (start > end) return -1; // target not found From 31c7021f875695beb59119cc308e631704a284df Mon Sep 17 00:00:00 2001 From: NickMezacapa <89874146+NickMezacapa@users.noreply.github.com> Date: Fri, 7 Oct 2022 12:59:49 -0700 Subject: [PATCH 5/5] omitted curly braces on if-else statement --- Search/BinarySearch.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Search/BinarySearch.ts b/Search/BinarySearch.ts index 1194b752..760a2c50 100644 --- a/Search/BinarySearch.ts +++ b/Search/BinarySearch.ts @@ -28,12 +28,10 @@ export const binarySearchIterative = (array: number[], target: number): number = 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]) { + if (target < array[middle]) end = middle - 1; - } - else { + else start = middle + 1; - } // redeclare the middle index when the search window changes middle = (start + end) >> 1; }