From 0de1aa1cd7ebbce8324b5668aa04ff50a6e8426e Mon Sep 17 00:00:00 2001 From: nickzerjeski Date: Mon, 13 Apr 2026 11:02:33 +0200 Subject: [PATCH 1/3] feat: add meta binary search algorithm Fixes: #1835 --- Search/MetaBinarySearch.js | 28 ++++++++++++++++++++++++++++ Search/test/MetaBinarySearch.test.js | 21 +++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 Search/MetaBinarySearch.js create mode 100644 Search/test/MetaBinarySearch.test.js diff --git a/Search/MetaBinarySearch.js b/Search/MetaBinarySearch.js new file mode 100644 index 0000000000..b0c19e9a72 --- /dev/null +++ b/Search/MetaBinarySearch.js @@ -0,0 +1,28 @@ +/** + * Meta Binary Search + * https://www.geeksforgeeks.org/meta-binary-search-one-sided-binary-search/ + * + * Builds the index bit by bit from the most-significant bit to the least-significant bit. + * Works on sorted arrays and returns the index of target, or -1 if not found. + */ + +function metaBinarySearch(sortedArray, target) { + if (!Array.isArray(sortedArray) || sortedArray.length === 0) { + return -1 + } + + const n = sortedArray.length + const maxBit = Math.floor(Math.log2(n - 1 < 0 ? 0 : n - 1)) + + let position = 0 + for (let bit = maxBit; bit >= 0; bit--) { + const candidate = position | (1 << bit) + if (candidate < n && sortedArray[candidate] <= target) { + position = candidate + } + } + + return sortedArray[position] === target ? position : -1 +} + +export { metaBinarySearch } diff --git a/Search/test/MetaBinarySearch.test.js b/Search/test/MetaBinarySearch.test.js new file mode 100644 index 0000000000..9b58cfd5b1 --- /dev/null +++ b/Search/test/MetaBinarySearch.test.js @@ -0,0 +1,21 @@ +import { metaBinarySearch } from '../MetaBinarySearch' + +describe('Meta Binary Search', () => { + test('returns index for found numeric element', () => { + expect(metaBinarySearch([2, 5, 8, 12, 16, 23, 38], 23)).toBe(5) + }) + + test('returns -1 when numeric element is missing', () => { + expect(metaBinarySearch([2, 5, 8, 12, 16, 23, 38], 9)).toBe(-1) + }) + + test('works with sorted strings', () => { + expect(metaBinarySearch(['alpha', 'beta', 'delta', 'omega'], 'delta')).toBe( + 2 + ) + }) + + test('returns -1 on empty input', () => { + expect(metaBinarySearch([], 1)).toBe(-1) + }) +}) From 3a48a803b0a3362bc3315c476527fc1bee9912a8 Mon Sep 17 00:00:00 2001 From: nickzerjeski Date: Mon, 13 Apr 2026 09:09:12 +0000 Subject: [PATCH 2/3] Updated Documentation in README.md --- DIRECTORY.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index b7b8aca45d..b3511a1372 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -314,6 +314,7 @@ * [InterpolationSearch](Search/InterpolationSearch.js) * [JumpSearch](Search/JumpSearch.js) * [LinearSearch](Search/LinearSearch.js) + * [MetaBinarySearch](Search/MetaBinarySearch.js) * [Minesweeper](Search/Minesweeper.js) * [QuickSelectSearch](Search/QuickSelectSearch.js) * [RabinKarp](Search/RabinKarp.js) @@ -322,8 +323,8 @@ * [TernarySearch](Search/TernarySearch.js) * [UnionFind](Search/UnionFind.js) * **Sliding-Windows** - * [MaxSumSubarrayFixed](Sliding-Windows/MaxSumSubarrayFixed.js) * [LongestSubarrayWithSumAtMost](Sliding-Windows/LongestSubarrayWithSumAtMost.js) + * [MaxSumSubarrayFixed](Sliding-Windows/MaxSumSubarrayFixed.js) * **Sorts** * [AlphaNumericalSort](Sorts/AlphaNumericalSort.js) * [BeadSort](Sorts/BeadSort.js) From b2269fc286e7f60fe31275a15efd1a5ffcbc2d1f Mon Sep 17 00:00:00 2001 From: nickzerjeski Date: Mon, 13 Apr 2026 12:18:00 +0200 Subject: [PATCH 3/3] Address review edge cases in meta binary search --- Search/MetaBinarySearch.js | 4 ++-- Search/test/MetaBinarySearch.test.js | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Search/MetaBinarySearch.js b/Search/MetaBinarySearch.js index b0c19e9a72..c2ef924516 100644 --- a/Search/MetaBinarySearch.js +++ b/Search/MetaBinarySearch.js @@ -12,11 +12,11 @@ function metaBinarySearch(sortedArray, target) { } const n = sortedArray.length - const maxBit = Math.floor(Math.log2(n - 1 < 0 ? 0 : n - 1)) + const maxBit = Math.floor(Math.log2(Math.max(1, n - 1))) let position = 0 for (let bit = maxBit; bit >= 0; bit--) { - const candidate = position | (1 << bit) + const candidate = position + 2 ** bit if (candidate < n && sortedArray[candidate] <= target) { position = candidate } diff --git a/Search/test/MetaBinarySearch.test.js b/Search/test/MetaBinarySearch.test.js index 9b58cfd5b1..1609c8ada3 100644 --- a/Search/test/MetaBinarySearch.test.js +++ b/Search/test/MetaBinarySearch.test.js @@ -18,4 +18,8 @@ describe('Meta Binary Search', () => { test('returns -1 on empty input', () => { expect(metaBinarySearch([], 1)).toBe(-1) }) + + test('returns index for a matching element in a single-element array', () => { + expect(metaBinarySearch([7], 7)).toBe(0) + }) })