Tuesday, September 22, 2020

[LeetCode] Find Minimum in Rotated Sorted Array

Problem: Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For example, the array nums = [0,1,2,4,5,6,7] might become:

  • [4,5,6,7,0,1,2] if it was rotated 4 times.
  • [0,1,2,4,5,6,7] if it was rotated 7 times.

Notice that rotating an array [a[0], a[1], a[2], ..., a[n-1]] 1 time results in the array [a[n-1], a[0], a[1], a[2], ..., a[n-2]].

Given the sorted rotated array nums of unique elements, return the minimum element of this array.

Example:

Input: nums = [3,4,5,1,2]
Output: 1
Explanation: The original array was [1,2,3,4,5] rotated 3 times.
Input: nums = [4,5,6,7,0,1,2]
Output: 0
Explanation: The original array was [0,1,2,4,5,6,7] and it was rotated 4 times.
Input: nums = [11,13,15,17]
Output: 11
Explanation: The original array was [11,13,15,17] and it was rotated 4 times. 


Approach: We are going to use binary search. While comparing the mid element, we would have these three conditions -

  1. arr[mid - 1] > arr [mid] < arr[mid + 1]. Got the minimum just return arr[mid]. We need to take care of boundary conditions here.
  2. arr[mid] > arr[high]. That's the only condition where the min element is on the right side. It happened because of rotation.
  3. Otherwise the min element is on left side.

Implementation in C#:

Using Recursion:

        public int FindMinInRotatedArray(int[] nums)
        {
            if (nums?.Length == 0)
            {
                return -1;
            }

            return this.FindMinInRotatedArray(nums, 0, nums.Length - 1);
        }

        private int FindMinInRotatedArray(int[] nums, int low, int high)
        {
            if (low == high)
            {
                return nums[low];
            }

            int mid = (low + high) / 2;

            if ((mid == nums.Length - 1 || nums[mid] < nums[mid + 1]) && 
                (mid == 0 || nums[mid] < nums[mid - 1]))
            {
                return nums[mid];
            }

            if (nums[mid] > nums[high]) // Go to right side
            {
                return FindMinInRotatedArray(nums, mid + 1, high);
            }
            else // Go to left side otherwise
            {
                return FindMinInRotatedArray(nums, low, mid - 1);
            }
        }


Without recursion:

        public int FindMinInRotatedArray(int[] nums)
        {
            if (nums?.Length == 0)
            {
                return -1;
            }

            int low = 0, high = nums.Length - 1;

            while(low < high)
            {
                int mid = (low + high) / 2;
                if (nums[mid] > nums[high])
                {
                    low = mid + 1;   
                }
                else
                {
                    high = mid;
                }
            }

            return nums[high];
        }


Complexity: O(logn)

No comments:

Post a Comment