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

示例 1:

输入:[3,4,5,1,2]
输出:1
示例 2:

输入:[2,2,2,0,1]
输出:0

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof

方法一:暴力解决:直接遍历获取这个数组的最小值。
方法二:利用二分查找。通过观察题目,题目中说明这个数组是一个递增排序的数组的一个旋转。因此旋转数组的最小值就是对应的旋转点,旋转点既小于前一个数字,同时小于/等于后一个数字,之所以说小于/等于,是因为存在旋转点是一个重复数字的情况

由于我们知道旋转点会比它前一个数字小,比他后一个数字小。所以我们需要将中间值numbers[mid]和最后一个数字numbers[ j ](j表示的是子数组的最后一个元素)进行比较,这时候就会存在三种情况:
①numbers[mid] > numbers[ j ],这时候就说明旋转点在中间值的右侧,所以调整子数组,使得i = mid + 1
②numbers[mid] < numbers[ j ],这时候就说明mid + 1 - j之间的数字大于中间值,说明旋转点在中间值的左边,或者中间值就是旋转点,所以调整j = m,而不是j = m - 1(因为存在当前的中间值就是旋转点的情况,例如[3, 1, 3]这个例子)
③numbers[mid] == numbers[ j ],并没有一定说明mid + 1 - j之间的数字都等于了中间值,存在中间值重复出现,在这些数字的中间还存在了更小的数字,所以调整应该是j–;

有可能会疑惑,为什么需要将中间值和最后一个数字进行比较呢?因为这样我们能够快速的找到旋转点所在位置的范围。我们都知道旋转点比前后两个数字都小,同时子数组是一个递增的数组,那么必然子数组的第一个元素小于最后一个元素,如果中间值大于最后一个元素,那么就说明了在中间值的右边会有值的变化,曲线图将会是先下降,然后再上升,所以旋转点再中间值的右边。同理,如果中间值小于了最后一个元素,说明中间值后面的元素都大于等于中间值的,所以说明了中间值可能就是旋转点,或者旋转点再中间值的左边;如果中间值等于了最后一个元素,那么就说明旋转点必定在两者之间,所以才会出现中间值等于最后一个元素的情况.

对应的代码:

class Solution {public int minArray(int[] numbers) {int i,j,mid;i = 0;j = numbers.length - 1;while(i <= j){mid = (i + j) / 2;//获取中间值//比较中间值,如果中间值大,说明旋转点在中间值的右边,所以i = m + 1if(numbers[mid] > numbers[j]) i = mid + 1;//中间值小于子数组最后一个元素,说明中间值是旋转点,或者旋转点在中间值的左边else if(numbers[mid] < numbers[j]) j = mid;//中间值等于子数组最后一个元素,说明旋转点在这两个数字之间else j--; }return numbers[i];}
}

运行结果:

基于上面的例子,我们再看看下面的题目:
整数数组 nums 按升序排列,数组中的值 互不相同
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array

那么本题的要求是再这个旋转数组中找到一个数,如果能找到这个数,那么就返回这个数的下标,否则返回-1.
如果这个数组是一个有序的数组,那么我们就可以直接利用二分查找的方式进行查找了,但是在这个题目中,nums是一个旋转之后的数组,所以nums这个数组是一个局部有序的数组,只要我们找到了枢纽的下标pivotIndex,那么我们就可以将整个数组划分成两个有序的数组了,此时只需要在这两个有序数组中找到target即可

对应的代码:

class Solution {/*利用的是二分查找的方法,需要找到中间的枢纽的下标,如果target和中间枢纽相等,那么直接返回这个枢纽的下标(题目已经明确说明各个元素的值互不相同),否则,如果target大于中间枢纽的值,如果target在中间枢纽的左边,否则,如果target小于枢纽的值,那么说明没有办法找到,那么直接返回-1*/public int search(int[] nums, int target) {if(nums == null || nums.length == 0)return -1;int pivotIndex = getPivotIndex(nums,0,nums.length - 1);// System.out.println(pivotIndex);if(pivotIndex == 0){//如果中间枢纽在下标为0的为止,说明整个数组都是升序的return binarySearch(nums,0,nums.length - 1,target);}else{if(nums[pivotIndex] == target) //如果中间枢纽就是target,直接返回对应的下标return pivotIndex;else{//如果中间枢纽不等于target,那么就分别在两个有序子数组中查找if(nums[nums.length - 1] < target) //如果target在中间枢纽的左边return binarySearch(nums,0,pivotIndex - 1,target);elsereturn binarySearch(nums,pivotIndex + 1,nums.length - 1,target);}}}//对nums数组中的low-high的数字进行二分查找public int binarySearch(int[] nums,int low,int high,int target){int mid;while(low <= high){mid = (low + high) / 2;if(nums[mid] == target)return mid;else if(nums[mid] > target)high = mid - 1;elselow = mid + 1;}return -1;}//获取中间枢纽的下标public int getPivotIndex(int[] nums,int low,int high){int mid = 0;while(low <= high){mid = (low + high) / 2;if(nums[mid] == nums[high])high--;//如果中间值等于最后一个元素还小,那么可能中间枢纽在两者之间,所以high--else if(nums[mid] < nums[high])//如果中间值小于最后一个元素,那么[mid + 1, high]的数字都是大于枢纽的数字,此时mid可能是枢纽,所以high = mid,而不是high = mid - 1high = mid;elselow = mid + 1;//如果中间值比最后一个元素还要大,那么说明中间枢纽在中间值之后}return mid;}
}

运行结果:

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

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

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

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

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

  3. leetcode 11:旋转数组的最小数字

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

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

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

  5. 剑指offer_第6题_旋转数组的最小数字

    题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋 ...

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

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

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

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

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

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

  9. 剑指Offer #06 旋转数组的最小数字(二分查找)| 图文详解

    题目来源:牛客网-剑指Offer专题 题目地址:旋转数组的最小数字 题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小 ...

最新文章

  1. 什么是SOLID原则(第3部分)
  2. 碰撞检测碰撞Java简单游戏开发之碰撞检测
  3. 莆田版GPT-3开源:同等复现预训练模型GPT Neo
  4. linux挂载和卸载
  5. git切换到远程分支
  6. 实战系列-分布式锁的Redis实现
  7. html5--3.19 新增的progress/meter元素
  8. 基于深度学习的超大面积室内导航机器人Java后台软件设计
  9. C语言 符号配对 (20分)
  10. 使用APICloud开发物流仓储app项目实践
  11. 连八股文都不懂还指望在后端混下去么
  12. 服装企业二维码应用现状,如何建立二维码营销平台规则体系?
  13. python打开txt文件以gbk,python中txt文件的编码转换问题utf-8转gbk
  14. Java常用日志框架介绍(转载)
  15. halcon模板匹配实践(5)使用橡皮擦涂抹功能实现减少模板匹配特征
  16. 传智 刘意 2015年Java基础视频-深入浅出精华版 笔记 day24~day26(2016年4月26日13:11:30)
  17. Touch in Android
  18. 汇总:所有你该知道的AR/VR/3D技术与发展
  19. Java数据结构——直接插入排序+希尔排序+冒泡排序
  20. 自定义xml配置文件之dtd文件校验

热门文章

  1. 简单财务软件有哪些功能?
  2. 使用XML、XSLT和XPath创建可排序、分页、重用的数据显示页面
  3. 数仓指标体系搭建实战(上)
  4. MATLAB零记忆非线性方法(ZMNL)相关韦布尔分布
  5. 矮人要塞 dwarf fortress
  6. 2506:沙漏图形 tri2str [1*+]
  7. 计算机网络与通信刘化君第三版答案,计算机网络与通信
  8. 基于最小费用流(MCF)法的相位解包裹理论与实验验证-含Matlab代码
  9. 404 not found是什么意思?该怎么解决?
  10. 【k8s】修改docker的docker.service并重启docker服务