求旋转排序数组的最小值

文章讲述了如何利用二分查找法在已知经过多次旋转的升序数组中找到最小元素。通过分析旋转规律,作者指出只需关注左边界和右边界的关系,最终确定最小值所在区间。
摘要由CSDN通过智能技术生成

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:

  • 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
  • 若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]

注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

要求:求最小元素

分析题目:旋转4次 可以得到【4,5,6,7,0,1,2】

不难发现:

数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。

我的想法是 想象成一个逆时针转动的圆盘

每一次转动 都会把数字最后面的元素提到最前面来

二分查找法  时间复杂度为 O(log n)

思路:在这里我们使用二分查找法,始终将最小值套住,去不断的收缩左边界或者右边界

分别去讨论左中右的情况:

左 <中<右:

没有发生旋转的情况,其中最小值依然是按顺序排列在最左边,这时候我们可以将右边界进行收缩。

左 >中>右:

逆序排列,单调递减,在3个元素以上是不可能出现这种情况的,所以pass掉

左 <中>右:

中间的最大,最小值在右边,收缩左边界,这里可以直接让left = mid+1

左 >中<右

中间的最小,最小值在左边,收缩右边界,但是不能判断mid所在的值是否为最小,所以不能把mid 直接忽略,让right = mid;即可

这里我们通过观察不难发现,其实归根结底只有两种情况,就是中<右  和 中>右(1和4类情况是一样的都是最小值在左边)

所以我们仅仅通过比较左值和右就可以确定收缩的方向

中间位置:将中间位置mid定义为int类型

所以mid会更接近left,这样解决了mid不是整数的问题,浮点数在计算过程中可能会出现精度丢失或溢出的情况,影响到二分查找的正确性

而且,可以确保 mid 更接近左边,从而有利于判断最小值所在的区间:原先的数是按照大小顺序排序的,左边的更小,右边的更大,要查找最小值,偏往左边寻找无疑是更有利于查找的

我们选择mid与right比较,为什么不和left去比较,刚开始这个问题也困扰了我良久,还是得结合前面的情况分析,跟右边比较无疑是更简单的,跟左边比较更适合用来寻找最大值,我们也可以转换思路,先找最大值,那紧挨的下一位肯定就是最小值(数组长度范围内,如果超出了就是a[0]最小值)

下面讨论一下循环条件while中的left <right

即当左右边界重合的时候,循环结束

学习算法的同时分享一些学习感想,如有错误,还希望大佬及时指出

  • 9
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值