amitabhmajhi2332005's blog

By amitabhmajhi2332005, history, 64 minutes ago, In English

The naive approach and its limits

The most straightforward way to find a value x in an array is a simple for loop:

for (int i = 0; i < n; i++) {
    if (array[i] == x) {
        // x found at index i
    }
}

This works perfectly — but its time complexity is O(n). In the worst case you inspect every element. For arbitrary (unsorted) arrays, this is actually optimal; you have no information about where x might be.

When does this become a problem? With n = 106 and 105 queries, you're doing 1011 operations — about 100× over a typical time limit.

But if the array is sorted, the situation changes entirely. Order carries information. Binary search exploits that information to find any element in O(log n) time.

Method 1 — classic halving

Think of how you look up a word in a dictionary. You open roughly to the middle, check whether the word comes before or after, then repeat on the relevant half. This is exactly what Method 1 implements.

The algorithm maintains an active region [a, b] in the array. At each step it checks the middle element and halves the region, until either the element is found or the region collapses.

int a = 0, b = n-1;
while (a <= b) {
    int k = (a+b)/2;
    if (array[k] == x) {
        // x found at index k
    }
    if (array[k] > x) b = k-1;
    else a = k+1;
}

The active region starts at size n and halves each iteration, giving at most ⌈log₂ n⌉ iterations — hence O(log n).

Method 2 — jump search variant

An alternative that's elegant to reason about: instead of tracking a region, track a jump length and walk forward.

int k = 0;
for (int b = n/2; b >= 1; b /= 2) {
    while (k+b < n && array[k+b] <= x) k += b;
}
if (array[k] == x) {
    // x found at index k
}

The outer loop runs ⌈log₂ n⌉ times and the inner while executes at most twice per jump length — so the total is still** O(log n)**

C++ STL functions

lower_bound	Pointer to first element ≥ x
upper_bound	Pointer to first element > x
equal_range	Both pointers as a pair

If no such element exists, all three point one past the last element. Here's how to check for x:

auto k = lower_bound(array, array+n, x) - array;
if (k < n && array[k] == x) {
    // x found at index k
}

Counting how many times x appears:

auto a = lower_bound(array, array+n, x);
auto b = upper_bound(array, array+n, x);
cout << b-a << "\n";

Using equal_range for the same result in one call:

auto r = equal_range(array, array+n, x);
cout << r.second - r.first << "\n";

In contests, prefer the STL functions whenever you just need a boundary — they're battle-tested and save debugging time. Write Method 1 or 2 explicitly when the predicate is non-standard (e.g. searching on a function's output rather than an array).

  • Vote: I like it
  • -10
  • Vote: I do not like it