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

文章目录

  • 【LeetCode】剑指 Offer 11. 旋转数组的最小数字
  • 一、遍历
  • 二、二分法
  • 总结

一、遍历

算法步骤:

  1. 遍历数组,只要后一个数大于前一个数就说明最小的数还在后面,找到后一个数小于前一个数就说明找到了
  2. 如果遍历完数组还是没有找到,那就说明后面每一个数都大于第 1 个数,因此第一个数是最小数
class Solution {public int minArray(int[] numbers) {int i = 0;while(i < numbers.length - 1 && numbers[i+1] >= numbers[i]){i++;}if(i+1 >= numbers.length){return numbers[0];}return numbers[i+1];}
}

二、二分法

思路与算法

一个包含重复元素的升序数组在经过旋转之后,可以得到下面可视化的折线图:

其中横轴表示数组元素的下标,纵轴表示数组元素的值。图中标出了最小值的位置,是我们需要查找的目标

我们考虑数组中的最后一个元素 x:在最小值右侧得元素,他们的值一定都小于等于 x;而在最小值左侧的元素,它们的值一定都大于等于 x。因此,我们可以根据这一条性质,通过二分查找的方法找出最小值

在二分查找的每一步中,左边界为 low,右边界为 high,区间的中点为 pivot,最小值就在该区间内。我们将中轴元素 numbers[pivot] 与右边界元素 numbers[high] 进行比较,可能会有以下的三种情况:

第一种情况是 numbers[pivot] < numbers[high]。如下图所示,这说明 numbers[pivot] 是最小值右侧的元素,因此我们可以忽略二分查找区间的右半部分

第二种情况是 numbers[pivot] > numbers[high]。如下图所示,这说明 numbers[pivot] 是最小值左侧的元素,因此我们可以忽略二分查找的区间的左半部分

第三种情况是 numbers[pivot] == numbers[high]。如下图所示,由于重复元素的存在,我们并不能确定 numbers[pivot] 究竟在最小值的左侧还是右侧,因此我们不能莽撞地忽略某一部分的元素。我们唯一可以知道的是,由于它们的值相同,所以无论 numbers[high] 是不是最小值,都有一个和它值相同的 numbers[pivot],因此我们可以忽略二分查找区间的右端点

当二分查找结束时,我们就得到了最小值所在的位置

class Solution{public int minArray(int[] numbers){int low = 0;int high = numbers.length - 1;while(low < high){int pivot = low + (high - low) / 2;if(numbers[pivot] < numbers[high]){high = pivot;} else if(numbers[pivot] > numbers[high]){low = pivot + 1;} else{high -= 1;}}return numbers[low];}
}
  • 时间复杂度:平均时间复杂度为 O(logn),其中 n 是数组 numbers 的长度。如果数组是随机生成的,那么数组中包含相同元素的概率很低,在二分查找的过程中,大部分情况都会忽略一半的区间。而在最坏情况下,如果数组中的元素完全相同,那么 while 循环就需要执行 n 次,每次忽略区间的右端点,时间复杂度为 O(n)
  • 空间复杂度:O(1)

总结


翻了翻题解的评论区,不得不感叹一下,即使你解出来了,但是没有用最优的解法,这道算法题在面试官眼里真的就是 0 分!这次我太急了,2 分钟就想出遍历的方法,就直接提交了。回想我第一次做 leetcode 的题时,俩小时没有解出一道简单题,把四大查找,八大排序都复习了一边,像从中找到灵感,但是这一次题目很明显是查找,我却没有深入思考,我本应该想到四大查找的,该死!

class Solution {public int minArray(int[] numbers) {if(numbers.length == 1){return numbers[0];}int mid = (numbers.length - 1) / 2;int i = mid;while(i < numbers.length - 1 && numbers[i+1] >= numbers[i]){i++;}if(i == numbers.length - 1 &&numbers[i] > numbers[0]){return numbers[0];}if(i+1 <= numbers.length - 1){return numbers[i+1] > numbers[0]?numbers[0]:numbers[i+1]; }i = mid;if(i == 0){return numbers[0] > numbers[1]?numbers[1]:numbers[0];}if(numbers[i] < numbers[i-1]){return numbers[i];}i = mid;while(i > 1 && numbers[i-1] <= numbers[i]){i--;}return numbers[i];}
}

这是我自己在得知要使用二分法后写的,用了很多判断语句,很复杂。虽然二分查找是要在一个有序的数组里查找,但是我感觉这一道题也是可以二分更多次的,但是又看到要进行那么多次的复杂判断,又感觉不行,最后看了的题解,果然是可以一直进行二分的,而且代码整体也要比我的简洁。看了题解的思路,发现是我将问题的情况划分得太多了,有的情况可以划分为一类,从而减少判断语句,对于学过的知识还是要活学活用啊

【LeetCode】剑指 Offer 11. 旋转数组的最小数字相关推荐

  1. Leetcode 剑指 Offer 11. 旋转数组的最小数字 (每日一题 20210916)

    把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转, ...

  2. leetcode剑指 Offer 11. 旋转数组的最小数字(二分查找)

    把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转, ...

  3. 《LeetCode力扣练习》剑指 Offer 11. 旋转数组的最小数字 Java

    <LeetCode力扣练习>剑指 Offer 11. 旋转数组的最小数字 Java 一.资源 题目: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 给你一个可能存在 ...

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

    剑指 Offer 11. 旋转数组的最小数字 题目 解题思路 方法(一)直接遍历法 方法(二)二分查找法 题目 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组 ...

  5. 剑指offer 11. 旋转数组的最小数字(很详细!)

    剑指offer 11. 旋转数组的最小数字 题目 解题思路 代码 题目 解题思路 一开始,我们就能直接想到,数组找最小值,那么不轻轻松松直接遍历一遍,用一个变量记录最小值,然后直接返回不就完事了? 但 ...

  6. 【剑指 Offe】剑指 Offer 11. 旋转数组的最小数字

    目录标题 算法汇总 题目 关键点 代码 1.解体方法 - 二分法 思路 代码 时间和空间复杂度 2.解题方法,如暴力法 思路 代码 时间和空间复杂度 算法汇总 以下是所有算法汇总,包括GitHub源码 ...

  7. 剑指offer——11.旋转数组的最小数字

    题目: 题1:实现快速排序 题2:年龄排序问题. 题3:旋转数组的最小数字 知识点: 快速排序算法,参考:https://blog.csdn.net/shujuelin/article/details ...

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

    把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转, ...

  9. 【双百解法】剑指 Offer 11. 旋转数组的最小数字

    立志用最少的代码做最高效的表达 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如,数组 [3,4,5,1,2] 为 [1 ...

最新文章

  1. 一文详解C++文件读写(FileStorage、txt)
  2. TIOBE 9 月排行榜:C++ 式微,第 3 名被 Python 拿下
  3. python第三十课--异常(raise关键字)
  4. larvare数据库引入php_PHP全栈学习笔记6
  5. WebDriver API 元素定位(三)
  6. SLAM - 01 - 分类
  7. WPF(Windows Presentation Foundation)用户界面框架
  8. 数据分析对企业的重要性
  9. android sdk的封装,Android封装SDK的使用
  10. 【电脑讲解】硬件知识
  11. android条码扫描串口,串口条码扫描器的正确安装方法[图解]
  12. windows下格式化内存卡
  13. WebRTC收集网卡地址信息 源码剖析
  14. python-flask 设置网页保留缓存静态文件时间
  15. 剖析SPDK读写NVMe盘过程--从hello_world开始
  16. 用树莓派搭建远程下载+私有云盘(中篇)
  17. Android开发——Snackbar使用详解
  18. pip 更换国内安装源 阿里源 清华源 豆瓣源等等
  19. InnerClass annotations are missing corresponding EnclosingMember annotations. Such InnerClas...
  20. 优化Windows xp Professional大全

热门文章

  1. php 购物车案例教程,php初步实现购物车功能的实例分析
  2. 华为大数据战略_任正非:华为应抓住“大数据”机遇 抢占战略制高点
  3. grafana官方使用文档_5. Centos7 下部署使用 nmon2influxdb
  4. java中Jackson_java 中的好东西 jackson
  5. python入门题目及答案_Python基础知识的一些练习与解答,python,部分,习题,及,答案...
  6. kubernetes ConfigMap和Secret:配置应用程序
  7. 动态排名系统(整体二分)
  8. 一个整数,它加上100后是一个完全平方数,加上168又是一个完全平方数,请问该数是多少?...
  9. The Largest Clique UVA - 11324( 强连通分量 + dp最长路)
  10. zoj 1676Network Wars(胡博涛论文题,01分数规划+最小割)