{x}
blog image

Search in a Sorted Array of Unknown Size

Solution Explanation: Search in a Sorted Array of Unknown Size

This problem involves finding a target value within a sorted array of unknown size. We can only access the array elements using an ArrayReader interface, which returns the value at a given index or 2^31 - 1 if the index is out of bounds. The challenge is to solve this efficiently, aiming for O(log n) time complexity, where n is the index of the target element (if it exists).

The solution leverages a modified binary search strategy. Because the array size is unknown, we first need to determine an upper bound for our search space. We do this by repeatedly doubling an index (r) until we find an element greater than or equal to the target. This initial phase ensures we have a range where the target might exist.

Once we have this upper bound, we can perform a standard binary search within that range. This approach is efficient because the initial doubling phase ensures a relatively small search space for the binary search.

Algorithm Steps:

  1. Find Upper Bound:

    • Start with r = 1.
    • While ArrayReader.get(r) < target, double r (r <<= 1 or r *= 2). This finds a value r such that ArrayReader.get(r) is greater than or equal to the target, or we reach the end of the array.
  2. Binary Search:

    • Set l = r >> 1 (or l = r / 2). This is our lower bound.
    • Perform a standard binary search within the range [l, r].
      • Calculate mid = (l + r) >> 1 (or mid = (l + r) / 2).
      • If ArrayReader.get(mid) >= target, update r = mid. The target is in the lower half (or potentially at mid).
      • Otherwise, update l = mid + 1. The target is in the upper half (if it exists).
    • The loop continues until l and r converge.
  3. Check and Return:

    • After the binary search, check if ArrayReader.get(l) == target. If true, return l (the index of the target). If false, return -1 (target not found).

Time Complexity Analysis

  • Finding Upper Bound: The loop doubling r runs at most log₂(n) times, where n is the index of the target (or the last element if the target is not present). This is because each iteration doubles the range we're searching.

  • Binary Search: The binary search on the interval [l, r] takes O(log(n)) time in the worst case.

Therefore, the overall time complexity is O(log n), dominated by the binary search phase.

Space Complexity Analysis

The space complexity is O(1) because we are only using a few constant extra variables to store the indices l, r, and mid.

Code Examples (Python, Java, C++, Go, TypeScript):

The provided code in various languages accurately implements the algorithm described above. Each version follows the same structure: the initial doubling phase followed by the binary search and final check. The bitwise operators (<<=, >>, etc.) are used for efficiency in some languages to perform multiplication and division by 2.