Binary search is fast because every comparison discards half of the remaining search space. The price of that speed is a strict precondition: the input must be sorted according to the same ordering used by the search.
1 | def binary_search(values, target) |
The invariant
At the start of every loop, if the target exists, it must be somewhere between left and right, inclusive. Each comparison preserves that invariant while shrinking the interval.
- Time complexity:
O(log n). - Space complexity:
O(1)for the iterative version.
The old recursive version mixed a loop with recursive calls. It could work, but it paid for two control-flow mechanisms while needing only one. Algorithms are already hard enough; they do not need decorative recursion.
Ruby also provides Array#bsearch_index for production code:
1 | numbers.bsearch_index { |value| value >= 5 } # => 4 |
Implement binary search to understand the invariant. Use the standard library when shipping software unless custom behavior is actually required.