• 剑指offer 旋转数组的最小数字


    题目描述

    把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
     
    思路:首先理解数组的旋转定义,可以发现旋转数组可以划分为两个非减排序的子数组,而最小元素在两个子数组的分界处。
    (1)我们用两个指针分别指向数组的第一个元素和最后一个元素,根据旋转数组定义,我们知道第一个元素应该是大于等于最后一个元素的。
    (2)找到数组的中间元素;
      如果中间元素位于前面的递增子数组,那么它应该大于等于第一个指针指向的元素,此时最小元素应该在中间元素的后面。我们把第一个指针指向中间元素。
      如果中间元素位于后面的递增子数组,那么它应该小于等于第二个指针指向的元素,此时最小元素应该在中间元素的前面,我们把第二个指针指向中间元素。
    可知,第一个指针始终指向前面递增子数组的元素,第二个指针总是指向后面递增子数组的元素。它们最终会相邻,而第二个指针会指向最小元素。这就是循环结束的条件。
     
    除此,我们还需要考虑一些特殊情况:
    1、数组未旋转,即旋转后的数组和原数组一致,那么第一个元素是最小元素。
    2、考虑有重复元素的情况:{1, 0, 1, 1, 1}, {1, 1, 1, 0, 1}
    我们无法判断中间元素属于前面的递增子数组还是属于后面的递增子数组,这时我们只能对左右指针所包围的数组进行顺序查找。
     
     1 class Solution {
     2 private:
     3     int minInOrder(vector<int> v, int index1, int index2) {
     4         // 找到最小元素的索引值
     5         int index = index1;
     6         for (int i = index1 + 1; i <= index2; i++) {
     7             if (v[i] < v[index]) {
     8                 index = i;
     9             }
    10         }
    11         return index;
    12     }
    13 public:
    14     int minNumberInRotateArray(vector<int> rotateArray) {
    15         int len = rotateArray.size();
    16         //如果数组长度小于等于0,返回0
    17         if (len <= 0) {
    18             return 0;
    19         }
    20         int index_l = 0;
    21         int index_r = len - 1;
    22         int indexMid = index_l; //一开始将指向中间元素的指针指向第一个元素,很好地解决了数组未旋转的情况
    23         //确保旋转
    24         while (rotateArray[index_l] >= rotateArray[index_r]) {
    25             //分界点
    26             if (index_r - index_l == 1) {
    27                 indexMid = index_r;
    28                 break;
    29             }
    30             //指向中间元素
    31             indexMid = index_l + (index_r - index_l) / 2;
    32             //如果index_l,indexMid, index_r指向的数字相等, 则只能顺序查找。如果index_l,index_r的指向的数字不相等,
    33             //那么肯定可以确定indexMid指向的元素是属于前(或后)面递增子数组的
    34             if (rotateArray[index_l] == rotateArray[index_r] && rotateArray[index_l] == rotateArray[indexMid]) {
    35                 indexMid = minInOrder(rotateArray, index_l, index_r);
    36                 break;
    37             }
    38             //如果中间元素大于等于第一个指针指向的元素,那么中间元素位于前面的递增子数组
    39             if (rotateArray[indexMid] >= rotateArray[index_l]) {
    40                 index_l = indexMid;
    41             }
    42             //如果中间元素小于等于第二个指针指向的元素,那么中间元素位于后面的递增子数组
    43             if (rotateArray[indexMid] <= rotateArray[index_r]) {
    44                 index_r = indexMid;
    45             }
    46         }
    47         return rotateArray[indexMid];
    48     }
    49 };
     
  • 相关阅读:
    [整理]修改git 默认编辑器为vim
    [转]如何清空Chrome缓存和Cookie
    [整理]docker内部时区修改的两种方法
    [译]10个有关SCP的命令
    [译]在python中如何有效的比较两个无序的列表是否包含完全同样的元素(不是set)?
    通过设计表快速了解sql语句中字段的含义
    [整理]什么是排序算法的稳定性,为什么它很重要?
    pyinstaller打包自己的python程序
    [问题解决]ps aux中command命令相同,如何找出自己要的进程号?
    [常识]Windows系统里休眠和睡眠的区别?
  • 原文地址:https://www.cnblogs.com/qinduanyinghua/p/11237678.html
Copyright © 2020-2023  润新知