0

I'm new to Javascript, and I'm wondering if there are any existing Javascript libraries which contain binary search functionality similar to C++ equal_range? I wrote a quick implementation of what I'm looking for:

/*
 * Javascript version of C++ equal_range via lower_bound and upper_bound
 *
 * Input: The array A in ascending order and a target T
 * Output: The tightly bound indices [i, j] where A[i] <= T < A[j] if T exists in A
 * otherwise [-1, -1] is returned if T does not exist in A
 */

let lowerBound = (A, T) => {
    let N = A.length,
        i = 0,
        j = N - 1;
    while (i < j) {
        let k = Math.floor((i + j) / 2);
        if (A[k] < T)
            i = k + 1;
        else
            j = k;
    }
    return A[i] == T ? i : -1;
};

let upperBound = (A, T) => {
    let N = A.length,
        i = 0,
        j = N - 1;
    while (i < j) {
        let k = Math.floor((i + j + 1) / 2);
        if (A[k] <= T)
            i = k;
        else
            j = k - 1;
    }
    return A[j] == T ? j + 1 : -1;
};

let equalRange = (A, T) => {
    return [lowerBound(A, T), upperBound(A, T)];
};
claytonjwong
  • 814
  • 1
  • 7
  • 13
  • Did you mean just sort in ascending order? Js have sort method – Thanveer Shah Jun 18 '20 at 16:11
  • I am aware of Array.prototype.sort(), however, that is not my question. I am looking for binary search functions to invoke upon an already sorted input array. – claytonjwong Jun 22 '20 at 17:48
  • That is not a correct implementation of std::lower_bound. from cppreference: _"Returns an iterator pointing to the first element in the range [first, last) that does not satisfy element < value (or comp(element, value)), (i.e. greater or equal to), or last `-1` if no such element is found."_ Your implementation returns `-1` for any element that is not found. – Orwellophile May 24 '23 at 13:06

2 Answers2

0

The Google closure-library may be the closest library I've found so far:

https://google.github.io/closure-library/api/goog.array.html

claytonjwong
  • 814
  • 1
  • 7
  • 13
0

Your code is incorrect, see attached comment regarding the incorrect return of -1 for any unfound element, when AFAIK -1 should never be returned (though provision appears to be made for such in the description, the demo code at https://en.cppreference.com/w/cpp/algorithm/lower_bound does not seem capable of returning -1 under any condition).

Therefore a more correct implementation would be:

function equalRange(array, value) {
  const lowerBoundIndex = lowerBound(array, value);
  const upperBoundIndex = upperBound(array, value);

  return [lowerBoundIndex, upperBoundIndex];
}

function lowerBound(array, value) {
  let low = 0;
  let high = array.length;

  while (low < high) {
    const mid = Math.floor((low + high) / 2);

    if (array[mid] < value) {
      low = mid + 1;
    } else {
      high = mid;
    }
  }

  return low;
}

function upperBound(array, value) {
  let low = 0;
  let high = array.length;

  while (low < high) {
    const mid = Math.floor((low + high) / 2);

    if (array[mid] <= value) {
      low = mid + 1;
    } else {
      high = mid;
    }
  }

  return low;
}

Example usage:

const sortedArray = [1, 2, 2, 3, 4, 4, 4, 5, 6];

const value1 = 4;
const range1 = equalRange(sortedArray, value1);
console.log(range1); // Output: [4, 7]

const value2 = 2;
const range2 = equalRange(sortedArray, value2);
console.log(range2); // Output: [1, 3]

const value3 = 7;
const range3 = equalRange(sortedArray, value3);
console.log(range3); // Output: [9, 9] (index beyond the end of the array)

In this example, equalRange takes a sorted array and a value as input. It uses the lowerBound and upperBound functions to find the lower bound and upper bound indices, respectively. It then returns a pair of indices representing the range of elements equal to the value. If the value is greater than all elements in the array, the function will return the index beyond the end of the array for both bounds.

Orwellophile
  • 13,235
  • 3
  • 69
  • 45