Leetcode refers to offer 11. Rotate the smallest number of arrays | Python

Time:2020-12-19

Rotate the smallest number in the array


Source: leetcode https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof

subject


Moving the first elements of an array to the end of an array is called array rotation. Input a rotation of an incremental sorted array and output the smallest element of the rotated array. For example, the array [3,4,5,1,2] is a rotation of [1,2,3,4,5], and the minimum value of the array is 1.

Example 1:

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

Example 2:

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

Note: this question is the same as 154 questions in the main station https://leetcode-cn.com/probl…

Thinking of problem solving


Idea: binary search

First examine the question and repeat the concept of rotation array. Here, rotating an array means placing the first elements of the array in ascending order at the end of the array.

Well, according to this concept, we can find out. After the array is rotated, the original array will be changednumsSplit into two ascending sorted arrays, set tonums1nums2And is placed at the end of the arraynums2Will be less than or equal to the preceding part of the arraynums1This is because the element may be repeated and will be analyzed later. Now the question is how to find the two ascending arrays after rotation? Because just find the two rotated arrays,nums2The first element in the array is the required answer.

Well, here, we can consider using the binary search method to find a dividing point (the dividing point is the first element placed at the end of the ascending array), and the array to the left of the demarcation point isnums1, the array to the right of the dividing point (including the dividing point) isnums2

The specific ideas are as followsnums1Represents the left ascending array after rotation,nums2Represents the right ascending array at the end of the rotation:

  • First, define the pointerleft,rightRespectively point tonumsArray, andmidIs the midpoint of each bisection search;
  • Start the comparison(nums1The element of is greater than or equal tonums2Elements of)There are three situations:

    • Ifnums[mid] > nums[right]When, thenmidBy all meansnums1In this array, the dividing point is in the interval(mid, right], orderleft=mid+1
    • Ifnums[mid] < nums[right]When, thenmidThen in thenums2In the array, the dividing point falls in the interval[left, mid], orderright=mid;
    • Ifnums[mid] == nums[right](this is because the elements are allowed to repeat), there will be a fuzzy boundary. First of all, let’s talk about the conclusion (later analysis), let’srightThe pointer moves forward, causingright -= 1

Here it isnums[mid] == nums[right]Suppose the given array is[1, 1, 0, 1]and[1, 0, 1, 1, 1]Then there will be the following situation

  • When given an array[1, 1, 0, 1]In this case,left = 0, right = 3, mid = 1

    • nums[mid] == nums[right]At this time, mid is in the array on the leftnums1Medium.
  • When given an array[1, 0, 1, 1, 1]At this timeleft = 0, right = 4, mid = 2

    • nums[mid] == nums[right], but the mid is in the array on the rightnums2Medium.

In this case, it is impossible to directly judge whether the mid falls in thenums1stillnums2Medium. In the previous conclusion, letright -= 1In order to solve this problem, according to the above analysis, the feasibility of this conclusion is analyzed

  • WhenmidFall onnums1Array becausenums1Any element of is greater than or equal tonums2In other words, let the boundary point bepointnums[point] <= nums[mid] == nums[right]Then:

    • ifnums[point] < nums[right]It is explained hererightThe element on the left also has a small valueright -= 1After that,pointIs it still there[left, right]In this interval;
    • Ifnums[point] == nums[right]We should pay attention to the dividing point indexpointAndrightIn the case of equality. At this time, makeright-=1At this timepointWill not be in[left, right]In this interval. Suppose you have the following array[1, 1, 2, 1]Here it isleft = 0, right = 3, mid = 1We can see that the dividing point is the last one. herepoint == right, ifright -= 1So the last one here1Will be discarded. But the end result will come back1Because we give up the last1After that, continue the binary search, and the cut-off point must fall on the[left, mid]And the values of the elements in this interval are equal tonums[point]。 So it can return the correct value.
  • WhenmidFall onnums2Array, that is to say[mid, right]The values of all elements in this interval are equal. At this timeright -= 1It just discards a duplicate value, andpointOr did it fall in[left, right]In this interval.

The following is an illustration of the algorithm implementation:

Leetcode refers to offer 11. Rotate the smallest number of arrays | Python

The specific implementation code is as follows.

code implementation


class Solution:
    def minArray(self, numbers: List[int]) -> int:
        left = 0
        right = len(numbers) - 1

        while left < right:
            #Take the midpoint
            mid = left + (right - left) // 2
            #If numbers [mid] > numbers [right], the dividing point falls on (mid, right]
            if numbers[mid] > numbers[right]:
                left = mid + 1
            #Numbers [mid] < numbers [right], the dividing point falls in [left, mid]
            elif numbers[mid] < numbers[right]:
                right = mid
            #Numbers [mid] = = numbers [right], let right - = 1. The feasibility of this conclusion has been analyzed in this paper
            else:
                right -= 1

        return numbers[left]

Achieving results


Leetcode refers to offer 11. Rotate the smallest number of arrays | Python

Welcome to our attention


The official account [book collection]