题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
牛客网上给的函数接口:
class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
}
}
分析:
看到题目的第一刻,我想的是既然这个数组原本是非递减排序的,那么在其旋转后,就分为了两个非递减的子序列,第一个子序列的值一定是大于或等于第二个子序列的,那么我们可以从第一元素开始往后遍历,只要前面的元素比它后面的一个元素大,说明第一个子序列的最后一个元素和第二个子序列的第一个元素相遇了,那么明显当前元素后面的那个元素就是最小元素了。当然还要判断若数组元素是否为空。
于是我开始动手写程序,如下:
class Solution {
 public:
    int minNumberInRotateArray(vector<int> rotateArray) {
int n=rotateArray.size( );
        if(n==0)
              return 0;
        for(int i=0;i<n-1;i++)
          {
              if(rotateArray[i]>rotateArray[i+1])
                  return  rotateArray[i+1];
          }
        return  rotateArray[0];
}
}
很神奇的是竟然通过了,我很兴奋,但是总觉得剑指offer上的题考虑的远远不止这,于是我打开课本,果然我很low,考虑的问题太少,复杂度是O(n)就不说,有的测试用例也没想到。      
       书上写的是利用二分查找的思想(复杂度为O(logn))来解决这个问题,因为前面说过对于一个旋转的数组来说,旋转后数组实际上分成了两个排序的子数组,而且前面的子数组的元素均大于后面子数组的元素。而且最小的元素刚好是两个子数组的分界。
       对于一个长度为n的数组,设置两个指针index1和index2,开始时index1指向第一个数组元素,即下标为0的位置,index2指向数组最后一个元素,及下标为n-1的位置。如果第一个元素大于最后一个元素,说明旋转了0个元素,输出第一个元素(最小)。否则找到数组中间位置indexMid的元素。indexMid=(index1+index2)/2。如果indexMid位置对应的值大于index1对应的值,那么说明indexMid位置对应的值位于第一个子数组中,最小值应该在indexMid后面,所以将indexMid赋给index1。如果indexMid位置对应的值小于index2对应的值,那么说明indexMid位置对应的值位于第二个子数组中,最小值应该在indexMid前面,所以将indexMid赋给index2。直到index1和index2的值相差1,即index1指向第一个子数组的最后一个位置,index2指向第二个子数组的第一个位置。读者可以自己以数组{3,4,5,1,2}分析。
        于是有代码:(红色代码部分说明见最下面)
class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        int n=rotateArray.size( );
        if(n==0)
           return 0;
        int index1=0;
        int index2=n-1;
        int indexMid=index1;   
        while(rotateArray[index1]>=rotateArray[index2])
          {
             if(index2-index1==1)    //注意不要搞反了减数和被减数
                 {
                    indexMid=index2;
                    break;
                 }   
             indexMid=(index1+index2)/2;
             //如果出现了下标index1、index2及indexMid三个值相等的情况,那么就只能是顺序查找了
             if(rotateArray[indexMid]==rotateArray[index1]&&rotateArray[index1]==rotateArray[index2])
                 {
                    return MinInOrder(rotateArray,index1,index2);
                 }
            
             if(rotateArray[indexMid]>=rotateArray[index1])
                    index1=indexMid;
             else if(rotateArray[indexMid]<=rotateArray[index2])
                    index2=indexMid;
                 
          }
        return rotateArray[indexMid];
    }
       int MinInOrder(vector<int> rotateArray,int index1,int index2)     //注意函数定义的位置,不要在函数minNumberInRotateArray内定义
           {
              int Min=rotateArray[index1];
              for(int i=index1+1;i<=index2;i++)
                 { if(Min>rotateArray[i])
                      Min=rotateArray[i];
                 }
              return Min;
           }
};
我们没有考虑到的一种情况是:如果index1、index2及indexMid对应的值相等怎么办?
       比如数组{1,0,1,1,1}和数组{1,1,1,0,1}都是原始非递减数组{0,1,1,1,1}的旋转数组。可以看到第一个元素、第三个元素以及第五个元素的值都是1,此时,我们不得不采用顺序查找的方法。

剑指offer面试题[8]-旋转数组的最小数字相关推荐

  1. 剑指Offer - 面试题11. 旋转数组的最小数字(二分查找)

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

  2. 剑指offer面试题11. 旋转数组的最小数字(二分查找)

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

  3. 剑指offer(12)旋转数组的最小数字

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

  4. 剑指offe面试题8 旋转数组的最小数字 (java实现)

    解题思路: 针对旋转数组的特点,即旋转后,数组的前半部分是有序的,后半部分是有序的. 1.先考虑一般情况:可以参考二分查找的思想,在数组中设置两个指针,一个指向数组的起始位置,一个指向数组的结束位置. ...

  5. j剑指offer面试题[33]-把数组排成最小的数

    题目描述 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323. 思路: 可以 ...

  6. 剑指Offer - 面试题45. 把数组排成最小的数(字符串排序)

    1. 题目 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个. 示例 1: 输入: [10,2] 输出: "102"示例 2: 输入: [ ...

  7. 剑指Offer:面试题33——把数组排成最小的数(java实现)(未完待续)

    问题描述: 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323. 思路1: ...

  8. 【剑指offer-Java版】08旋转数组的最小数字

    旋转数组最小数字:暴力方法就是遍历-有效的方法是二分,但是存在失效的情况 几个特别的测试用例需要注意下: 数组中含有多个相同的数字 最小数字就是第一个 public class _Q08 {publi ...

  9. 剑指offer——面试题51:数组中重复的数字

    剑指offer--面试题51:数组中重复的数字 Solution1: 20180910更新.利用数组做一次hash映射,时间复杂度为O(n)O(n)O(n),空间复杂度O(n)O(n)O(n). cl ...

最新文章

  1. 如何编译和运行C++程序
  2. 小猿圈linux之运维工程师面试题(答案版)
  3. 皮一皮:听说这是功夫熊猫风的情侣酒店...
  4. 蓝桥杯--2013--黄金连分数(大数)
  5. 什么是机房三维(3D)监控系统,什么是机房可视化动力环境监控系统?
  6. mysql maria引擎_MySQL体系结构和存储引擎概述
  7. 防止私自接交换机_防止私接家用路由器干扰DHCP功能,禁止用户手动设置IP地址-肖哥...
  8. SAP WebClient UI界面元素ID生成的逻辑分析
  9. Vs Code如何自定义设置一键代码补全
  10. 分披萨问题_比萨问题–建造者与装饰者
  11. 使用Spring Boot和Spring Security验证JWT
  12. my.ini优化mysql数据库性能的十个参数(推荐)
  13. Linux系统上的程序调优思路概要
  14. jedis jedispool Redistemplate
  15. SQL不重复查找数据及把一列多行内容拼成一行
  16. 一道隐藏欺诈的JavaScript面试题
  17. one hot encoding
  18. 数据推荐 | 自然场景OCR文字识别数据集一览
  19. 企业数字化转型战略权威指南
  20. .NET Core技术研究-通过Roslyn代码分析技术规范提升代码质量

热门文章

  1. Cassandra Leveled Compaction源码阅读
  2. 韩国大面积断网事情,可能遭受了DDoS攻击,网友:真的是黑客攻击吗?
  3. android显示字符串,Android自定义View用切图显示字符串
  4. javascript中打印对象显示[object object]_扒一扒JavaScript中不常见的一些object
  5. Pytorch 基本概念
  6. COM的八个经验和教训
  7. linux oracle 12170,ora-12170 linux
  8. 学hadoop需要什么基础
  9. !!!后续博客写到简书 + 博客园留博客目录
  10. 指数体系与因素分析:概念、作用与种类