题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{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. pandas使用split函数将dataframe中的特定列表字段(list column)裂变为多个数据列并拼接到原dataframe中
  2. C/C++中未定义行为
  3. c++连接mongodb出错
  4. 项目: 互动粒子仿真
  5. boost::enable_shared_from_this相关的测试程序
  6. 方差分析数据.rar
  7. Java字符串String相关2
  8. python邮件发送csv附件_Python2.7 smtplib发送带附件邮件报错STARTTLS解决方法
  9. IOS9+基础之警报框弹出和操作表弹出
  10. jeesite使用心得(二)
  11. OpenStack Glance简介
  12. Java web servers 间是如何实现 session 同步的
  13. TensorFlow推出命令式、可定义的运行接口Eager Execution
  14. linux查看服务命令是什么,linux系统查看所有服务的命令
  15. SBC在企业IP通信系统中的应用
  16. 一些Winodws mobile相关资料的整理
  17. JavaScript树形下拉框
  18. 多云管理平台解决方案
  19. Windows系统解决谷歌翻译不能用的问题
  20. 外媒如何看鸿蒙系统实测,鸿蒙系统是否真的很难成功,为何外媒总是在不断的“贬低”它?...

热门文章

  1. 去掉QQ2008的腾讯迷你首页和聊天时的广告
  2. 注塑机摆放间距多少合适_垃圾分类盛行,生产塑料环卫垃圾桶的注塑机怎么选?...
  3. 简单高效有用的正则表达
  4. 聚能聊每周精选 第十五期
  5. [译][Tkinter 教程15] event 事件绑定
  6. 如何在通用用户权限系统中快速实现调查问卷系统
  7. output在delete中的应用
  8. string.Format 格式化输出
  9. chapter1.4.4
  10. 判断Sbo的Matrix中是否存在相同数据行