Problem Statement in English

You’re given an integer array nums sorted in non-decreasing order (not necessarily with distinct values). Before being passed to your function, nums is rotated at an unknown pivot index k (0 <= k < nums.length) such that the resulting array is [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]] (0-indexed).

Return true if target is in nums, or false if it is not.


Approach

Although it seems intimidating, we can still use a very slightly modified binary search to solve this problem.

We need to identify if the left half or right half is sorted, but one half is guaranteed to be sorted.

Since we don’t particularly know which half the target is in, if at all, we deal with something we can actually be sure about: check if the target is in the sorted half. If it is, we can narrow our search to that half. If not, we can narrow our search to the other unsorted half, and repeat the exact same process.

In order to find the sorted half, we can compare the leftmost and middle elements. If the leftmost element is less than or equal to the middle element, then the left half is sorted. Otherwise, the right half is sorted.

There’s also a special case we need to handle: if the leftmost, middle, and rightmost elements are all equal, we can’t determine which half is sorted. In this case, we can simply move the left pointer one step to the right and the right pointer one step to the left, effectively narrowing our search space.

And we’re done!


Solution in Python


class Solution:
    def search(self, nums: list[int], target: int) -> bool:
        left, right = 0, len(nums) - 1

        while left <= right:
            mid = (left + right) // 2

            if nums[mid] == target:
                return True

            # Handle duplicate edge case: unable to determine sorted half
            if nums[left] == nums[mid] == nums[right]:
                left += 1
                right -= 1
            # Left half is sorted
            elif nums[left] <= nums[mid]:
                if nums[left] <= target < nums[mid]:
                    right = mid - 1
                else:
                    left = mid + 1
            # Right half is sorted
            else:
                if nums[mid] < target <= nums[right]:
                    left = mid + 1
                else:
                    right = mid - 1

        return False

Complexity

  • Time: $O(\log n)$
    Since we are using a binary search approach, the time complexity is logarithmic with respect to the number of elements in the array.

  • Space: $O(1)$
    Since we are using a constant amount of extra space (only a few variables), the space complexity is constant.


And we are done.