Searching & SortingProblem 3 of 36

Search in a rotated sorted array

Brute Force
Time: O(n)
Space: O(1)
Optimal
Time: O(log n)
Space: O(1)

Problem Statement

Given a sorted array that has been rotated at some pivot unknown to you beforehand, search for a target value. If found, return its index; otherwise, return -1.

Constraints:

  • Array was originally sorted in ascending order
  • Array is rotated at some pivot point
  • All elements are distinct

Example:

  • Input: nums = [4, 5, 6, 7, 0, 1, 2], target = 0
  • Output: 4
  • Explanation: 0 is found at index 4

Example 2:

  • Input: nums = [4, 5, 6, 7, 0, 1, 2], target = 3
  • Output: -1
  • Explanation: 3 is not in the array

Example 3:

  • Input: nums = [1], target = 0
  • Output: -1

Approach 1: Brute Force (Linear Search)

Intuition

Simply scan through all elements to find the target.

Algorithm

  1. Traverse the array from index 0 to n-1
  2. If current element equals target, return index
  3. Return -1 if target not found
java
public class Solution {
    public int search(int[] nums, int target) {
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == target) {
                return i;
            }
        }
        return -1;
    }
}

Complexity Analysis

  • Time Complexity: O(n) - May need to check all elements
  • Space Complexity: O(1) - No extra space

Approach 2: Modified Binary Search (Optimal)

Intuition

Even though the array is rotated, at least one half is always sorted. We can determine which half is sorted and check if the target lies in that half.

Key Observations:

  1. If nums[left] <= nums[mid], the left half is sorted
  2. If nums[mid] <= nums[right], the right half is sorted
  3. Check if target lies in the sorted half, adjust search accordingly

Algorithm

  1. Initialize left = 0 and right = n-1
  2. While left <= right:
    • Calculate mid
    • If nums[mid] == target, return mid
    • Determine which half is sorted:
      • If left half is sorted (nums[left] <= nums[mid]):
        • If target is in range [nums[left], nums[mid]), search left
        • Else search right
      • Else right half is sorted:
        • If target is in range (nums[mid], nums[right]], search right
        • Else search left
  3. Return -1 if not found
java
public class Solution {
    public int search(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        
        while (left <= right) {
            int mid = left + (right - left) / 2;
            
            if (nums[mid] == target) {
                return mid;
            }
            
            // Left half is sorted
            if (nums[left] <= nums[mid]) {
                // Target in left sorted half
                if (nums[left] <= target && target < nums[mid]) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            }
            // Right half is sorted
            else {
                // Target in right sorted half
                if (nums[mid] < target && target <= nums[right]) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
        }
        
        return -1;
    }
}

Dry Run Example

nums = [4, 5, 6, 7, 0, 1, 2], target = 0 Step 1: left=0, right=6, mid=3 nums[mid]=7, target=0, not equal nums[left]=4 <= nums[mid]=7, left half sorted target=0 not in [4, 7), so left = mid + 1 = 4 Step 2: left=4, right=6, mid=5 nums[mid]=1, target=0, not equal nums[left]=0 <= nums[mid]=1, left half sorted target=0 in [0, 1), so right = mid - 1 = 4 Step 3: left=4, right=4, mid=4 nums[mid]=0, target=0, FOUND! Return 4

Complexity Analysis

  • Time Complexity: O(log n) - Binary search
  • Space Complexity: O(1) - Only using pointers

Approach 3: Find Pivot + Binary Search

Intuition

First find the rotation point (smallest element), then perform standard binary search on the appropriate half.

java
public class Solution {
    private int findPivot(int[] nums) {
        int left = 0, right = nums.length - 1;
        
        while (left < right) {
            int mid = left + (right - left) / 2;
            
            if (nums[mid] > nums[right]) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        
        return left;
    }
    
    private int binarySearch(int[] nums, int left, int right, int target) {
        while (left <= right) {
            int mid = left + (right - left) / 2;
            
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        
        return -1;
    }
    
    public int search(int[] nums, int target) {
        if (nums.length == 0) return -1;
        
        int pivot = findPivot(nums);
        
        // If no rotation
        if (pivot == 0) {
            return binarySearch(nums, 0, nums.length - 1, target);
        }
        
        // Decide which half to search
        if (target >= nums[0]) {
            return binarySearch(nums, 0, pivot - 1, target);
        } else {
            return binarySearch(nums, pivot, nums.length - 1, target);
        }
    }
}

Handling Duplicates

When array contains duplicates, the worst case becomes O(n).


Key Takeaways

  1. Key Insight: At least one half of the array is always sorted
  2. Modified Binary Search: Check which half is sorted, then decide search direction
  3. Pivot Point: The minimum element indicates the rotation point
  4. Duplicates: Make the problem harder; worst case becomes O(n)
  5. Edge Cases: Single element, no rotation, target at pivot
  6. Common Pattern: This technique applies to many rotated array problems (find min, find peak, etc.)