旋转数组的概念:

把一个数组最开始的若干个元素搬到数组的末尾,就是旋转数组。
例如: 数组{1,2,3,4,5}的一个旋转数组就是{3,4,5,1,2},把1,2放数组的后面。

题目:

  • 输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素

思路:

这题最直观的解答就是遍历一遍数组,直接找出其中最小的元素。时间复杂度是O(n)。但是没有利用旋转数组的特性。
我们可以再来看看旋转数组:

旋转数组的特性:

  • 可以拆分为两个排好序的子数组
  • 前面的子数组的元素大于或者等于后面子数组的元素。
  • 最小的数组恰好是这两个数组的分界线。

举例说明:

旋转数组在一定程度上是排序的,因此试试用二分法找最小的元素。
直接举例说明,

我们以数组{3,4,5,1,2},指定两个指针,一个指向第一个元素3,一个指向最后一个元素2,如下图所示。位于两个指针中间的元素是5,它大于第一个指针指向的元素。因此中间数字5一定是前面的递增子数组中的元素,故最小的元素一定位于它的后面。所以移动第一个指针指向中间,如图所示,缩小查询范围。

这时,位于两个指针中间的元素是1,1小于第一个指针指向的元素,所以数字1位于后面的递增子数组中,故最小元素在数字1的前面或者就是数字1,这时将第二个指针指向数字1,缩小查询范围,如图所示。

此时,两个指针的距离是1,所欲第一个指针指向的是前面的递增子数组的最后一个元素,即最大的元素;第二个指针指向的是后面的递增子数组中第一个元素,即最小的元素,这就找到了。

代码(继续看下去)

def MinInOrder(array):if array == None or len(array) <= 0:   # 排除空集return falsel = 0                    # 定义左指针r = len(array) - 1       # 定义右指针while(array[l] >= array[r]):  if r - l == 1:          # 当左右指针相邻时,说明找到了,右指针指向的就是最小的元素return array[r]breakmid = l + ((r - l) >> 1)    # mid是中间元素的indexif array[mid] > array[l]:   # 若中间元素大于左指针指向的元素,说明最小元素在其后,故缩小查询范围l = midelse:                   # 反之同理r = midreturn array[mid]
输入:
array = [3,4,5,1,2]
MinInOrder(array)
输出:1

别急,还没有完,其实还有两个问题没考虑到

问题一:

前面说旋转数组是把前面部分元素搬到后面去,这没错,但是有个特殊情况,那就是我把前面0个元素搬到后面去,即旋转数组还是自己本身,哈哈哈,是不是有意思了。

这个时候,数组中最小的元素就是第一个元素了,我们试着运行上的代码:

输入:
array = [1,2,3,4,5]
MinInOrder(array)
输出:5

看见没有。输出的是5,最大的元素找出来,但我们要的是最小的元素,所以我们得改改代码

问题二:

看个例子,数组{0,1,1,1,1} 现在有两个旋转数组 {1,0,1,1,1} 和数组 {1,1,1,0,1}

看上图,会发现,左右指针指向的元素和中间元素是一样,这个时候,就不知道中间元素到底是前面的递增子数组还是后面的递增子数组,所以无法缩小查找范围。这时我们就得采用顺序查找的方式了。看完整的代码:

class Solution:def Min(self,array):if array == None or len(array) <= 0:   # 排除空集return Falsel = 0                    # 定义左指针r = len(array) - 1       # 定义右指针mid = 0                  # 将指针mid初始为0,一旦发现数组第一个元素小于最后一个元素,即数组是排序的(问题一),这直接返回while(array[l] >= array[r]):  if r - l == 1:          # 当左右指针相邻时,说明找到了,右指针指向的就是最小的元素return array[r]breakmid = l + ((r - l) >> 1)    # mid是中间元素的index# 如果左指针、右指针指向的元素和中间元素一致时(问题二),采用顺序查找if array[l] == array[mid] == array[r]:return self.MinOrder(array,l,r)if array[mid] > array[l]:   # 若中间元素大于左指针指向的元素,说明最小元素在其后,故缩小查询范围l = midelse:                   # 反之同理r = mid# 如果左指针、右指针指向的元素和中间元素一样,则只能顺序查找return array[mid]def MinOrder(self,array,l,r):     # 顺序查找,循环遍历所有元素,找最小的元素re = array[l]for i in range(l+1,r):if re > array[i]:re = array[i]return reif __name__ == "__main__":# 验证# 功能测试:输入数组升序数组的一个旋转数组,数组中有重复或在没有重复的数字test1 = [3,4,5,1,2]test2 = [1,0,1,1,1]# 边界测试:输入数组只有一个元素test3 = [5]# 特在测试:输入数组是空test4 = []solution = Solution()print("test_1:", solution.Min(test1))print("test_2:", solution.Min(test2))print("test_3:", solution.Min(test3))print("test_4:", solution.Min(test4))
输出:
test_1: 1
test_2: 0
test_3: 5
test_4: None

简写

def minNumberInRotateArray(rotateArray):# write code here# 二分查找:找左右的方法:右边的值大于中指时,说明最小值在左边,反之if rotateArray == None:   # 排除空集return 0left = 0          # 定义左指针right = len(rotateArray) -1   # 定义右指针while left <= right:mid = (right + left) >> 1     # 定义中间指针if rotateArray[mid] < rotateArray[mid-1]:    # 若中间指针对应的元素恰好小于前一个元素,说明当前元素就是最小的元素return rotateArray[mid]elif rotateArray[mid] < rotateArray[right]:  # 若中间元素小于最右边的元素,说明最小值在左边,更新指针right = mid-1else:                              # 反之left = mid+1return 0

11、旋转数组的最小数字相关推荐

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

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

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

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

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

    剑指 Offer 11. 旋转数组的最小数字 思路一:先排序,返回第一个数组值 class Solution {public:int minArray(vector<int>& n ...

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

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

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

    [LeetCode]剑指 Offer 11. 旋转数组的最小数字 文章目录 [LeetCode]剑指 Offer 11. 旋转数组的最小数字 一.遍历 二.二分法 总结 一.遍历 算法步骤: 遍历数组 ...

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

    题目:剑指 Offer 11. 旋转数组的最小数字 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数 ...

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

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

  8. 11. 旋转数组的最小数字(剑指 Offer 题解Java版)

    文章目录 11. 旋转数组的最小数字 题目描述 题目链接 解题思路 可以借助下图理解过程 代码 11. 旋转数组的最小数字 题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. ...

  9. 剑指offer:面试题11. 旋转数组的最小数字

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

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

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

最新文章

  1. PCL:PCLPlotter可视化特征直方图
  2. 【Maven实战】之基础知识点
  3. Go 语言编程 — 使用 delve 进行 DEBUG 调试
  4. 【Kafka】Kafka为什么要加入分区的概念
  5. mongodb 查询 mysql_MongoDB 基本查询使用
  6. vnc--centos 7 安装和配置
  7. HDU4577(2013年ACM杭州赛区邀请赛B题)
  8. arm qt5 iconv 问题
  9. 90TB显存!英伟达发布新一代SuperPod超算,AI算力新巅峰!
  10. SSH:hql语句传参报错,及antlr-2.7.2.jar重复包的删除
  11. Ubuntu中anaconda的安装及使用
  12. 第二课--C语言基础(1,2部分--共三部分)
  13. 猫眼(门镜)中的光学
  14. Linear-chain CRF的推导
  15. 高效管理MacOS中文件的技巧
  16. python 成语库_Python“Every Other Element”成语
  17. 高通qxdm抓取sensor的log【学习笔记】
  18. 汇编语言与微机接口——交通灯设计
  19. 吕广渝:上帝视角看公司运营
  20. python中forward(200)什么意思_Python中的Phyllotaxis模式| 算法植物学的一个单位

热门文章

  1. “后T+0”时代:基金电商人以变应变
  2. (转)谭志勇、赵微:区块链技术在中国商品交易市场的应用与发展
  3. 阿里集团公布2022“研究型实习生”计划
  4. 陈绪:7月24日阿里云上海峰会出品人
  5. c语言怎样用vc绘图,大佬们,小菜鸟想问一问用vc编译器做简易画图软件
  6. 【扩频通信】基于matlab GUI扩频通信系统仿真(带面板)【含Matlab源码 1587期】
  7. 【图像提取】基于matlab DNA编解码多尺度形态学提取眼前节组织【含Matlab源码 1191期】
  8. 【车间调度】基于matlab粒子群算法求解生产调度问题【含Matlab源码 485期】
  9. 【多目标优化求解】基于matlab金鹰算法求解多目标优化问题【含Matlab源码 188期】
  10. DeepStyle(第2部分):时尚GAN