剑指Offer-旋转数组的最小数字

75 阅读1分钟

题目

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个升序的数组的一个旋转,输出旋转数组的最小元素。 例如数组 {3,4,5,1,2}{3,4,5,1,2} 为 {1,2,3,4,5}{1,2,3,4,5} 的一个旋转,该数组的最小值为 11。 数组可能包含重复项。

注意:数组内所含元素非负,若数组大小为 00,请返回 −1−1。

数据范围

数组长度 [0,90][0,90]。

样例

输入:nums = [2, 2, 2, 0, 1]

输出:0

解析

本题使用二分的思想:

  1. 当最后一段等于第一个元素时,不满足二分的性质,就要n--直到满足二分的性质
  2. 删掉最后一段水平的数据后,若nums[n] >= nums[0]此时就时完全单调的,直接返回nums[0]就行
  3. 剩余的部分就使用二分的思想: 当num[mid] < num[0]时就取左边;否则取右边

代码

C++

class Solution {
public:
    int findMin(vector<int>& nums) {
        int n = nums.size() - 1;
        if (n < 0) return -1;
        
        while (n > 0 && nums[0] == nums[n]) n -- ;
        
        if (nums[n] > nums[0]) return nums[0];
        
        int l = 0, r = n;
        while (l < r) {
            int mid = l + (r - l) / 2;
            if (nums[mid] < nums[0]) r = mid;
            else l = mid + 1; 
        }
        
        return nums[l];
    }
};

Python

class Solution:
    def findMin(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums) - 1
        if n < 0:
            return -1
        while n > 0 and nums[n] == nums[0]:
            n -= 1
        if nums[n] >= nums[0]:
            return nums[0]
        l, r = 0, n
        while l < r:
            mid = (l + r) // 2
            if nums[mid] < nums[0]:
                r = mid
            else:
                l = mid + 1
        return nums[r]
                

GO

func findMin(nums []int) int {
    n := len(nums) - 1
    if n < 0 {
        return -1
    }
    for n > 0 && nums[n] == nums[0] {
        n -- 
    }
    if nums[n] > nums[0] {
        return nums[0]
    }
    
    l, r := 0, n
    for l < r {
        mid := l + (r - l) / 2
        if nums[mid] < nums[0] {
            r = mid
        } else {
            l = mid + 1
        }
    }
    return nums[l]
}