• 【剑指Offer】6、旋转数组的最小数字


      题目描述:

      把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

      解题思路:

      本题的直观解法很简单,直接对数组进行一次遍历就可以找到最小值,复杂度为O(n),但是显然这不是本题的意图所在,因为没有利用到任何旋转数组的特性。

      进一步分析,如果整个数组是有序的,那我们一定会想到用折半查找来实现。对于旋转数组,我们发现,它实际上可以划分为两个排序的子数组,而且前面数组的元素都不小于后面数组的元素,并且最小值正好就是这两个数组的分界线,由此,我们可以得出以下解决方法。

      首先用两个指针low和high分别指向数组的第一个元素和最后一个元素,然后可以找到中间元素mid。对于这个中间元素,有以下两种情况:(1)该元素大于等于low指向的元素,此时最小的元素说明在mid的后面,可以把low=mid;(2)中间元素小于等于high指向的元素,那么最小元素在mid之前,可以high=mid。特别注意:这里不要+1或者-1,因为只有这样才能保证low始终在第一个数组,high始终在第二个数组。依次循环,当最后low和high相差1时,low指向第一个数组的最后一个,high指向第二个数组的第一个(即为我们要找的最小值)。

      很明显,以上查找的时间复杂度为O(logN)。

      除此之外,本题还有两个特殊情况:

    • 将数组前0个元素移动到后面(相当于没有旋转,数组整体有序)。明显我们上面的分析没有包含这种情况,需要特殊处理,方法也很简单,将第一个元素和最后一个元素相比,若第一个元素小于最后一个元素,则说明最小值就是的第一个元素,可以直接返回。

    • 首尾指针指向的数字和中间元素三者都相等时,无法判断中间元素位于哪个子数组,无法缩小问题规模。此时,只能退而求其次,进行顺序查找。

      编程实现(Java):

        public int minNumberInRotateArray(int [] array) {
            /*
            三种情况:
            (1)把前面0个元素搬到末尾,也就是排序数组本身,第一个就是最小值
            (2)一般情况二分查找,当high-low=1时,high就是最小值
            (3)如果首尾元素和中间元素都相等时,只能顺序查找
            */
            int len=array.length;
            if(len==0)
                return 0;
            int low=0,high=len-1;
            if(array[low]<array[high]) //排序数组本身
                return array[low];
            while(low<high){
                int mid=low+(high-low)/2;
                if(array[low]==array[mid] && array[high]==array[mid])
                    return minInOrder(array);
                if(array[mid]>=array[low])
                    low=mid;
                else if(array[mid]<=array[high])
                    high=mid;
                if(high-low==1)
                    return array[high];
            }
            return -1;
        }
        public int minInOrder(int [] array) { //顺序查找
             int min=array[0];
             for(int num:array){
                 if(num<min)
                     min=num;
             }
              return min;
         }
    
  • 相关阅读:
    MySQL query_cache_type 详解
    MySQL validate_password 插件
    MySQL冷备份的跨操作系统还原
    MySQL5.7新特性笔记
    MySQL参数详解
    保存mysql用户的登录信息到~.my.cnf文件;用于方便登录操作。
    MySQL应用层传输协议分析
    python egg
    MySQL 加锁处理分析
    train_test_split, 关于随机抽样和分层抽样
  • 原文地址:https://www.cnblogs.com/gzshan/p/10735252.html
Copyright © 2020-2023  润新知