剑指 Offer 11. 旋转数组的最小数字

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

  1. 我第一时间想到的方法,遍历(估计是面试不能过系列)
    思路:因为是递增数组旋转,旋转后为两个递增数组的拼接,则最小值一定是数组的第一个元素(未旋转),或数组后面小于数组第一个元素的第一个元素。
    时间复杂度O(n),空间复杂度O(1)

    class Solution(object):
        def minArray(self, numbers):
            """
            :type numbers: List[int]
            :rtype: int
            """
            if len(numbers) == 0:
                return -1
            result = numbers[0]
            for i in range(1, len(numbers)):
                if numbers[i] < result:
                    result = numbers[i]
                    break
            return result
    

    在这里插入图片描述

  2. python真的是一门好语言

    class Solution(object):
       def minArray(self, numbers):
           """
           :type numbers: List[int]
           :rtype: int
           """
           return min(numbers)
    

    在这里插入图片描述

  3. 二分法,时间复杂度降低为O(logn) 这个应该是面试官想要的
    思路:判断数组中间元素与数组首位,末尾元素大小关系
    因为翻转后的数组中所有元素必都小于翻转点元素,则
    a. 判断若末尾元素大于首位元素,则数组未进行翻转。注意等于情况不能确定,譬如3,1,3
    b. 判断末尾元素小于首位元素,则判断数组进行了翻转。需要找到翻转数组的开始节点
    1. 如果中间节点大于首节点,则最小元素一定在【中间节点-尾节点】之间
    2. 如果中间节点小于首节点,则最小节点一定在【首节点-中间节点】之间
    3. 如果中间节点等于首节点,这个情况比较复杂,主要是要考虑到
    1)若中间节点等于首节点小于尾节点,则为首节点小于尾节点情况,直接返回首节点
    2)若中间节点大于尾节点,则最小数在中间节点和尾节点之间
    3)若中间元素等于尾节点,譬如3,1,3,3,3,或3,3,3,1,3,无法判断最小值位置,则收缩方式改为忽略数组的首节点,因为首节点与中间节点值相同,忽略首节点不会导致最小值被忽略。

    递归法

    class Solution(object):
    def minArray(self, numbers):
        """
        :type numbers: List[int]
        :rtype: int
        """
        if len(numbers) == 0:
            return -1
        if len(numbers) == 1:
            return numbers[0]
        if len(numbers) == 2:
            if numbers[0] < numbers[1]:
                return numbers[0]
            else:
                return numbers[1]
        if numbers[-1] > numbers[0]:
            return numbers[0]
        mid = len(numbers) / 2
        if numbers[mid] > numbers[0]:
            return self.minArray(numbers[mid+1:])
        elif numbers[mid] < numbers[0]:
            return self.minArray(numbers[0:mid+1])
        else:
            return self.minArray(numbers[1:])
        
        return -1
    

    耗时比第一种直接遍历都要长,呵呵哒了,递归真心不推荐,但是代码写出来是真的好看
    在这里插入图片描述

    迭代法
    边界地方尤其麻烦,需要找几种例子画一画,不然很容易写错

    class Solution(object):
    def minArray(self, numbers):
        """
        :type numbers: List[int]
        :rtype: int
        """
        if len(numbers) == 0:
            return -1
        if len(numbers) == 1:
            return numbers[0]
        if len(numbers) == 2:
            if numbers[0] < numbers[1]:
                return numbers[0]
            else:
                return numbers[1]
        if numbers[-1] > numbers[0]:
            return numbers[0]
        begin = 0
        end = len(numbers) - 1
        mid = end / 2
        while (end - begin) > 1:
            if numbers[end] > numbers[begin]:
                return numbers[begin]
            if numbers[mid] > numbers[begin]:
                begin = mid + 1
                mid = (begin + end) / 2
            elif numbers[mid] < numbers[begin]:
                end = mid
                mid = (begin + end) / 2
            else:
                begin = begin + 1
                mid = (begin + end) / 2
        if end == begin:
            return numbers[begin]
        else:
            if numbers[end] > numbers[begin]:
                return numbers[begin]
            else:
                return numbers[end]
        return -1
    

怎么说呢,废了半天劲
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值