Solution: Search in Rotated Sorted Array

Let's solve the Search in Rotated Sorted Array problem using the Modified Binary Search pattern.

Statement#

Given a sorted integer array, nums, and an integer value, target, the array is rotated by some arbitrary number. Search and return the index of target in this array. If the target does not exist, return -11.

An original sorted array before rotation is given below:

g array 1 10 20 47 59 63 75 88 99 107 120 133 155 162 176 188 199 200 210 222

After rotating this array 6 times, it changes to:

g array 176 188 199 200 210 222 1 10 20 47 59 63 75 88 99 107 120 133 155 162

Constraints:

  • All values in nums are unique.
  • The values in nums are sorted in ascending order.
  • The array may have been rotated by some arbitrary number.
  • 11 \leq nums.length 1000\leq 1000
  • 104-10^4 \leq nums[i] 104\leq 10^4
  • 104-10^4 \leq target 104\leq 10^4

Solution#

So far, you’ve probably brainstormed some approaches and have an idea of how to solve this problem. Let’s explore some of these approaches and figure out which one to follow based on considerations such as time complexity and any implementation constraints.

Naive approach#

A naive approach is to traverse the whole array while searching for our target.

We get the required solution, but at what cost? The time complexity is O(n)O(n) because we traverse the array only once, and the space complexity is O(1)O(1). Let’s see if we can use the modified binary search pattern to design a more efficient solution.

We’ve been provided with a rotated array to apply binary search, which is faster than the above linear approach. We can change the part we have to search based on our three pointers—low, mid, and high.

The slides below illustrate how we would like the algorithm to run:

Created with Fabric.js 3.6.6 target: 200 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 176 188 199 200 210 222 1 10 20 47 59 63 75 88 99 107 120 133 155 162 This is our initial setup.

1 of 13

Created with Fabric.js 3.6.6 target: 200 low 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 176 188 199 200 210 222 1 10 20 47 59 63 75 88 99 107 120 133 155 162 mid high Let's initialize our low, mid, and high pointers.

2 of 13

Created with Fabric.js 3.6.6 target: 200 low 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 176 188 199 200 210 222 1 10 20 47 59 63 75 88 99 107 120 133 155 162 mid high We compare the values of the low, mid, and high pointers. Since array[mid] < array[high], we know that the section from mid to high is sorted.

3 of 13

Created with Fabric.js 3.6.6 target: 200 low 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 176 188 199 200 210 222 1 10 20 47 59 63 75 88 99 107 120 133 155 162 mid high We also check if the target value lies in this section's range (47–162) and since it doesn't, we will continue our search in the section between the low and mid pointers.

4 of 13

Created with Fabric.js 3.6.6 target: 200 low 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 176 188 199 200 210 222 1 10 20 47 59 63 75 88 99 107 120 133 155 162 mid high We update the high pointer to mid -1. We can also discard the section to the right of the mid pointer.Once high pointer is updated, we can also update our mid pointer.

5 of 13

Created with Fabric.js 3.6.6 target: 200 low 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 176 188 199 200 210 222 1 10 20 47 59 63 75 88 99 107 120 133 155 162 mid high We compare the values of the low, mid, and high pointers. Since array[mid] > array[low], we know that the section from low to mid is sorted.

6 of 13

Created with Fabric.js 3.6.6 target: 200 low 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 176 188 199 200 210 222 1 10 20 47 59 63 75 88 99 107 120 133 155 162 mid high We also check if the target value lies in this section's range (176–210) and since it does, we will continue our search in the section between the low and mid pointers.

7 of 13

Created with Fabric.js 3.6.6 target: 200 low 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 176 188 199 200 210 222 1 10 20 47 59 63 75 88 99 107 120 133 155 162 mid high We compare the values of the low, mid, and high pointers. Since array[mid] > array[low], we know that the section from low to mid is sorted.

8 of 13

Created with Fabric.js 3.6.6 target: 200 low 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 176 188 199 200 210 222 1 10 20 47 59 63 75 88 99 107 120 133 155 162 mid high We check if the target value lies in this section's range (176–188) and since it doesn't, we will continue our search in the section between the mid and high pointers.

9 of 13

Created with Fabric.js 3.6.6 target: 200 low 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 176 188 199 200 210 222 1 10 20 47 59 63 75 88 99 107 120 133 155 162 mid high We update the low pointer to mid + 1. We can also discard the section to the left of the mid pointer.Once low pointer is updated, we can also update our mid pointer.

10 of 13

Created with Fabric.js 3.6.6 target: 200 low 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 176 188 199 200 210 222 1 10 20 47 59 63 75 88 99 107 120 133 155 162 mid high We compare the values of the low, mid, and high pointers. Since array[mid] < array[high], we know that the section from mid to high is sorted.

11 of 13

Created with Fabric.js 3.6.6 target: 200 low 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 176 188 199 200 210 222 1 10 20 47 59 63 75 88 99 107 120 133 155 162 mid high We check if the target value lies in this section's range (199–200) and since it does, we will continue our search in the section between the mid and high pointers.

12 of 13

Created with Fabric.js 3.6.6 target: 200 low 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 176 188 199 200 210 222 1 10 20 47 59 63 75 88 99 107 120 133 155 162 mid high We update the low pointer to mid + 1. We can also discard the section to the left of the mid pointer.Once low pointer is updated, we can also update our mid pointer. Our mid pointer now points to the target value.

13 of 13

Note: In the following section, we will gradually build the solution. Alternatively, you can skip straight to just the code.

Step-by-step solution construction#

Let’s start with learning how to use binary search to find a target value in an unrotated sorted array. We can do this either iteratively or recursively. Let’s look at the iterative version first.

Search in Sorted Array

Next, let’s look at the recursive version.

Search in Sorted Array

Binary search works with arrays that are completely sorted. However, the nums array that we’re provided may not have this property if it’s rotated. Therefore, we have to modify our binary search to accommodate this rotation.

You may notice that at least one half of the array is always sorted—if the array is rotated by less than half the length of the array, at least the second half of the array will still be sorted. Contrarily, if the array is rotated by more than half the length of the array, then at least the first half of the array will be sorted. We can use this property to our advantage and modify the binary_search function as follows:

  • If the target value lies within the sorted half of the array, our problem is a basic binary search.

  • Otherwise, discard the sorted half and keep examining the unsorted half.

Here is how we go about implementing the iterative approach for this:

Search in Rotated Sorted Array

The recursive approach is shown below:

Search in Rotated Sorted Array

Just the code#

Here’s the complete solution to this problem:

The iterative approach:

Search in Rotated Sorted Array

The recursive approach:

Search in Rotated Sorted Array

Solution summary#

To recap, the solution to this problem can be divided into the following five parts:

  1. Divide the array into two halves.

  2. Check if the first half is sorted, and if it is, do the following.

    • Check if the target lies in this range, and if it does, perform a binary search on this half for the target value.

    • If the target does not lie in this range, move to the second half of the array.

  3. If the first half is not sorted, check if the target lies in the second half.

    • If the target lies in this half, perform a binary search on this half for the target value.

    • If the target does not lie in the second half, examine the first half.

  4. If the target value is not found at the end of this process, we return -11.

Time complexity#

The time complexity of both approaches is O(logn)O(\log n) since we divide the array into two halves at each step.

Space complexity#

The space complexity of the iterative solution is O(1)O(1) since no new data structure is being created.

The space complexity of the recursive solution is O(logn)O(\log n), where nn is the number of elements present in the array and logn\log n is the maximum number of recursive calls needed to find the target.

Search in Rotated Sorted Array

Final Remarks