首页 > 其他分享 >【剑指Offer】6、旋转数组的最小数字

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

时间:2023-06-14 22:45:12浏览次数:45  
标签:Offer 元素 mid 旋转 high 最小值 low 数组

【剑指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;
     }

标签:Offer,元素,mid,旋转,high,最小值,low,数组
From: https://www.cnblogs.com/bujidao1128/p/17481551.html

相关文章

  • 数组
    数组指在连续内存空间中存储一组相同类型的元素数组通过索引实现访问O(1)数组通过遍历整个数组来实现搜索O(N)插入和删除的时间复杂度都是O(N)特点是适合读不适合写1.创建数组2.添加元素3.访问元素4.修改元素5.删除元素6.遍历数组7.查找元素8.数组的长度9.数组排序 4......
  • [C++/PTA] 有序数组(类模板)
    题目要求实现一个类模板,它可以接受一组数据,能对数据排序,也能输出数组的内容。每行输入的第一个数字为0,1,2或3:为0时表示输入结束;为1时表示将输入整数,为2时表示将输入有一位小数的浮点数,为3时表示输入字符。如果第一个数字非0,则接下来将输入一个正整数,表示即将输入的数据的数量......
  • HLS - 数组优化
    参考https://blog.csdn.net/zhangningning1996/article/details/107444387https://blog.csdn.net/pc153262603/article/details/106385483https://www.xilinx.com/htmldocs/xilinx2017_4/sdaccel_doc/eil1504034361560.html1.空间复杂度程序的两个衡量指标:时间复杂度......
  • 数组的扁平化
    请编写一个函数,它接收一个 多维数组 arr和它的深度n,并返回该数组的 扁平化 后的结果。多维数组 是一种包含整数或其他 多维数组 的递归数据结构。数组扁平化是对数组的一种操作,定义是将原数组部分或全部子数组删除,并替换为该子数组中的实际元素。只有当嵌套的数组深......
  • 数据结构和算法——旋转打印链表
    1、问题描述输入参数nn为正整数,如输入n=5n=5,则按行打印如下的数字:2、问题的理解这个问题是将数字1…n21…n2按照一圈一圈的方式......
  • 有效的山脉数组
    给定一个整数数组arr,如果它是有效的山脉数组就返回 true,否则返回false。让我们回顾一下,如果arr 满足下述条件,那么它是一个山脉数组:arr.length>=3在 0<i <arr.length-1 条件下,存在 i 使得:arr[0]<arr[1]<...arr[i-1]<arr[i]arr[i]>arr[i+1]>...>......
  • 每日一道leetcode:4. 寻找两个正序数组的中位数
    1.题目(困难)题目链接给定两个大小分别为m和n的正序(从小到大)数组nums1和nums2。请你找出并返回这两个正序数组的中位数。算法的时间复杂度应该为O(log(m+n))。示例1:输入:nums1=[1,3],nums2=[2]输出:2.00000解释:合并数组=[1,2,3],中位数2示例2:输入:nums1=[1,2],nu......
  • 【数据结构和算法面试题】左旋转字符串
    问题分析:本题是常见的旋转字符串的问题,解决的方法是两步旋转的方法:方法:voiddo_reverse(char*p_start,char*p_end){ if(NULL==p_start||NULL==p_end||p_start>p_end)return; chartmp; while(p_start<p_end){ tmp=*p_start; *p_start=*p_end; *p_end......
  • 代码随想录算法训练营第七天| 344.反转字符串 、 541. 反转字符串II、 剑指Offer 05.
     344.反转字符串代码:1voidreverseString(vector<char>&s){23inti=0;4intj=s.size()-1;5while(i<j)6{7charmid=s[i];8s[i]=s[j];9s[j]=mid;1011i++;12......
  • 【数据结构与算法面试题】子数组的最大和
    题目来源“数据结构与算法面试题80道”。问题分析:在数组的每一个位置处保存当前的最大值,当前的最大值组成为:解决方案:intget_max_subarray(int*a,intlength,bool&is_array_ok){ if(NULL==a||length<=0){ is_array_ok=false; return0; } int*p_h_a=(int*......