当前位置 博文首页 > guoziqing506的博客:寻找旋转排序数组中的最小值

    guoziqing506的博客:寻找旋转排序数组中的最小值

    作者:[db:作者] 时间:2021-09-03 15:16

    题目描述:假设一个旋转排序的数组其起始位置是未知的(比如:0 1 2 4 5 6 7 可能变成是:4 5 6 7 0 1 2)。你需要找到其中最小的元素。你可以假设数组中不存在重复的元素。

    样例:给出[4,5,6,7,0,1,2] ?返回 0

    从本质上讲,跟排序数组中查找target是一个道理。但是有两点不同:(1)是一个经过旋转的排序数组。(2)找的是最小的元素

    首先,我们可以把一个排序数组先分割成两部分[first, second],其中,first代表前面几个元素,second代表之后的,例如,对于数组[0, 1, 2, 4, 5, 6, 7],可以设定first = [0, 1, 2], second = [4, 5, 6, 7]. 那么,经过旋转之后,数组就变成了[second, first],我们观察一下,这个新数组有这样两个特性:(1)second中所有元素都大于first中任意元素(2)second与first都是递增的序列

    那么,我们的目标很明确了:寻找second的第一个元素。还是用二分法(关于二分查找的基础介绍,详见:点击打开链接),代码如下:

    class Solution:
        # @param num: a rotated sorted array
        # @return: the minimum number in the array
        def findMin(self, num):
            left, right = 0, len(num) - 1
            while left < right and num[left] > num[right]:
                mid = (left + right) // 2
                # mid指在second中
                if num[left] <= num[mid]:
                    left = mid + 1
                # mid指在first中
                elif num[left] > num[mid]:
                    right = mid
            return num[left]
            # write your code here

    这里,循环的条件增加了一个:num[left] > num[right],目的是为了让循环中left始终指向second中的元素,同时,对于未旋转的数组,使其一开始就不进入循环。而left < right的条件设定,则是为了让left始终和right不指向同一个元素。

    循环中,通过比较num[left]与num[mid]的值来判断mid所在的位置,不断逼近first的第一个元素。最后,left会指向second之后的第一个元素,也就是first的第一个元素,循环也就在此时结束。

    总结来说,就是二分查找,但是对于数组边界的处理需特别小心。


    cs