Recycled array solution to Find minimum in Rotated sorted Array

Question:

I am working on a hard but stupid bisect search problem and debugging for hours.

Find Minimum in Rotated Sorted Array II

  1. Find Minimum in Rotated Sorted Array II

Hard

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).

Find the minimum element.

The array may contain duplicates.

Example 1:

Input: [1,3,5]
Output: 1

Example 2:

Input: [2,2,2,0,1]
Output: 0

Note:

The widely accepted answer takes O(n) time,

class SolutionK:
    def findMin(self, nums):
        lo, hi = 0, len(nums)-1
        while lo < hi:
            mid = (hi +lo) // 2
            if nums[mid] > nums[hi]:
                lo = mid + 1
            elif nums[mid] < nums[hi]:
                hi = mid 
            else:
                hi -= 1      
        return nums[lo] 
    # why not min(nums)  or brute force

I think the problem might be solved by a recycled array.

Since there are duplicates, we can find the rightmost max, then max + 1 is the minimal.

#the mid
lo = 0
hi = len(nums)
mid = (lo+hi) // 2
mid = mid % len(nums)

and the terminating condition

if nums[mid-1] <= nums[mid] > nums[mid+1]: return mid as the peak.

Unfortunately I cannot design the decreasing conditions.

Could you please give some hints?

Asked By: AbstProcDo

||

Answers:

You can indeed use bisection. In case the array consists of only unique numbers and has been rotated either the leftmost or the rightmost value will be out of order with respect to the middle point. That is array[0] <= array[len(array) // 2] <= array[-1] will be False. On the other hand this condition may hold if:

  • the array is not rotated at all,
  • or there are duplicates such as [1, 1, 1, 1, 2] => (rotate left 1) [1, 1, 1, 2, 1].

So we can separately check the left and right part of the condition (array[0] and array[-1] respectively) and in case one of them is invalidated check the corresponding sub-array (the left and right sub-array respectively). In case neither condition is invalidated we need to check both sides and compare.

The following is an example implementation (it only uses min where there are less than three elements involved, i.e. a simple comparison could be made as well):

def minimum(array):
    if len(array) <= 2:
        return min(array)
    midpoint = len(array) // 2
    if array[0] > array[midpoint]:
        return minimum(array[:midpoint+1])
    elif array[midpoint] > array[-1]:
        return minimum(array[midpoint+1:])
    else:  # Possibly dealing with duplicates.
        return min(minimum(array[:midpoint]),
                   minimum(array[midpoint:]))

from collections import deque
from random import randint, choices

for test in range(1000):
    l = randint(10, 100)
    array = deque(sorted(choices(list(range(l // 2)), k=l)))
    array.rotate(randint(-len(array), len(array)))
    array = list(array)
    assert min(array) == minimum(array)
Answered By: a_guest

The easiest solution you can find is here. All you need to focus on mid-element. and other condition you can think of.

  public int findMin(int[] nums) {

        if(nums.length == 1) {
            return nums[0];
        }

        if (nums[0] < nums[nums.length - 1]){
            return nums[0];
        }

        int index = pivotRotatedIndex(nums);

        if (index == nums.length - 1) {
           return nums[0];
        }

        return nums[index+1];
    }

   static int pivotRotatedIndex(int[] nums)  {

        int l = 0;
        int r = nums.length - 1;


        while (l <= r) {

            int m = l + (r - l)/2;

            if (nums[l] > nums[l+1]){
                return l;
            }

            if (nums[m] > nums[m+1]) {
                return m;
            }

            if (nums[m-1] > nums[m]) {
                return m-1;
            }
            
      
            if (nums[m] < nums[l]) {
                r = m;
            }else {
                l = m;
            }


        }
        return  -1;

    }

Answered By: Thakar Sahil
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.