面试题11:旋转数组的最小数字

题目:把一个数组最开始的若千个元素搬到数组的末尾,我们称之为
数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小
元素。例如,数组{3,4,5,1,2}为{1,2, 3,4, 5}的一个旋转,该数组的最小
值为1

我们注意到旋转之后的数组实际上可以划分为两个排序的子数组,而
且前面子数组的元素都大于或者等于后面子数组的元素。我们还注感到最
小的元素刚好是这两个子数组的分界线。在排序的数组中我们可以用二分
查找法实现Olog)的查找。本题给出的数组在一定程度上是排序的,
因此
我们可以试着用二分查找法的思路来寻找这个最小的元素。
和二分查找法一样, 我们用两个指针分别指向数组的第一一个元索和最
后一个元素。按照题目中旋转的规则,第一个元素应该是大于或者等于最
后一个元素的(这其实不完全对,还有特例,后面再加以讨论)。
接着我们可以找到数组中间的元素。如果该中间元素位于前面的递增
子数组,那么它应该大于或者等于第一个指针指向的元素。此时数组中最
小的元素应该位于该中间元素的后面。我们可以把第一一个指针 指向该中间
元素,这样可以缩小寻找的范围。移动之后的第一个指针仍然位于前面的
递增子数组。
同样,如果中间元素位于后面的递增子数组,那么它应该小于或者等
于第二个指针指向的元素。此时该数组中最小的元素应该位于该中间元素
的前面。我们可以把第二个指针指向该中间元素,这样也可以缩小寻找的
范围。移动之后的第二个指针仍然位于后面的递增子数组。
不管是移动第一一个指针还是第 二个指针,查找范围都会缩小到原来的
一半。接下来我们再用更新之后的两个指针重复做新一轮的 查找。
按照上述思路,第一个指针总是指向前面递增数组的元素,而第二个
指针总是指向后面递增数组的元素。最终第一个指针将指向前面子数组的
最后一个元素,而第二个指针会指向后面子数组的第个元素。 也就是它
们最终会指向两个相邻的元素,而第二个指针指向的刚好是最小的元素。
这就是循环结束的条件。
以前面的数组{3,4,5,1,2}为例,我们先把第一个指针指向第0个
元素,把第二个指针指向第4个元素,如图2.13 (a) 所示。位于两个
指针中间(在数组中的下标是2)的数字是5,它大于第一个指针指向
的数字。因此中间数字5一定位于第一个递增子数组,并且最小的数字
一定位于它的后面。因此我们可以移动第一个指针,让它指向数组的中
间,如图2.13 (b)所示。
此时位于这两个指针中间(在数组中的下标是3)的数字是1,它小于
第二个指针指向的数字。因此这个中间数字1-定位于第二个递增字数组,
并且最小的数字–定位于它的前面或者它自己就是最小的数字。因此我们
可以移动第二个指针,让它指向两个指针中间的元素,即下标为3的元素,
如图2.13 ©所示。
在这里插入图片描述

# 面试题11 旋转数组的最小数字
'''
此道面试题是二分查找的变式,比较有意思,时间复杂度为O(logn)
解题的突破点在于画图。
'''
def Min(lis):
    if not isinstance(lis,list)  or  not lis:
        return 
    start,end = 0,len(lis)-1
    mid = start
    while lis[start]>=lis[end]:
        if end - start==1:
            mid = end
            break
        mid =start+ int((end-start)/2)
        if lis[start]==lis[mid]==lis[end]:
            mid = MinInOrder(lis,start,end)
            break
        if lis[mid]>=lis[start]:
            start = mid
        elif lis[mid]<=lis[end]:
            end = mid
    return lis[mid]
def MinInOrder(lis,start,end):
    val,min = lis[start],start
    for i in range(start,end+1):
        if lis[i]<val:
            val= lis[i]
            min=i
    return min
if __name__ == '__main__':
    lis = [3,4,5,1,2]
    lis1 = [1,2,3,4,5]
    lis2 = [1,0,1,1,1]
    print(Min(lis2))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
非常感谢您的提问,以下是我的回答: 1. Spring Boot的自动配置原理: Spring Boot的自动配置是基于条件注解实现的。Spring Boot会根据classpath中的jar包、类、属性等信息,来决定是否需要给容器中添加配置类。如果需要添加,则会根据条件自动配置底层框架,如Tomcat、Redis、MySQL等。如果不需要添加,则不会添加。 2. Spring Boot导入其他的配置文件: Spring Boot可以通过在application.properties或application.yml文件中添加spring.config.import属性来导入其他的配置文件。例如,可以添加以下内容来导入另一个配置文件: ``` spring.config.import=classpath:/another-config.yml ``` 3. Spring Boot的核心注解: Spring Boot的核心注解包括@SpringBootApplication、@Configuration、@EnableAutoConfiguration和@ComponentScan。其中@SpringBootApplication是一个复合注解,包含了@Configuration、@EnableAutoConfiguration和@ComponentScan注解的功能。 4. Spring Boot的实现: Spring Boot的实现基于Spring框架,它使用了大量的注解来简化配置。它还使用了条件注解来根据不同条件自动配置底层框架。另外,Spring Boot还提供了很多starter包,可以让开发人员更加方便快速地搭建应用程序。 5. Spring Boot和Spring MVC的区别: Spring Boot是一个快速构建基于Spring的应用程序的框架,它使用了很多注解来简化配置。而Spring MVC是一个基于MVC架构的Web应用程序框架,它是Spring框架的一部分。Spring Boot可以使用Spring MVC来构建Web应用程序,但是它还可以用于构建其他类型的应用程序。 6. Spring Boot如何跨域请求: Spring Boot可以通过添加一个跨域请求的过滤器来实现跨域请求。具体来说,可以创建一个类实现javax.servlet.Filter接口,然后在类上添加@WebFilter注解,并设置urlPatterns属性来指定需要跨域请求的URL。在过滤器实现的doFilter方法中,设置Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers和Access-Control-Max-Age等跨域请求头信息即可。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值