0

The following is a slightly modified implementation of binary search that finds the first occurrence of an Integer key.

Is this still O(log n)? I'm having some trouble determining whether this becomes O(n) in the worst case.

private static Integer lowestRank(Integer[] a, Integer key) {
    Integer lo = 0;
    Integer hi = a.length - 1;

    while (lo <= hi) {
        Integer mid = lo + ((hi - lo) / 2);
        if (key.compareTo(a[mid]) > 0) {
            lo = mid + 1;
        } else if (key.compareTo(a[mid]) < 0) {
            hi = mid - 1;

        // Modified here to return the first occurrence of the key, if it exists
        } else if (lo < mid) {
            hi = mid;

        } else {
            return mid;
        }
    }

    return -1;
}
albertjorlando
  • 202
  • 2
  • 9

2 Answers2

1

Yes, it is still O(log(n)). The third conditional statement only runs if key.compareTo(a[mid]) == 0 (because the previous two conditionals eliminate the inequality cases) and if lo < mid.

If the key exists exactly once in the array, this branch will happen at most once; if the key does not exist, it will not happen at all. Since the conditional itself as well as everything in the body of the conditional is a constant time operation, the running time remains O(log(n)).

What if the key occurs multiple times? First, what's the purpose of this conditional branch anyways:

else if (lo < mid) {
    hi = mid;
}

If lo < mid, it means we haven't scanned the full range of the list. Thus, we set hi = mid, thereby establishing mid as the upper bound for our search.

Thus, even if the key occurs multiple times, the search range is halved at every iteration.

ubadub
  • 3,571
  • 21
  • 32
1

Assuming we model individual statements as O(1), then our overall complexity is dictated by the number of loop iterations.

The number of iterations can only be O(n) if we're reducing the range ([lo, hi)) by a constant amount per iteration (on average). In all three relevant cases, it should be evident that that's not the case - the range is always halving, on average.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680