• 006 旋转数组的最小数字


    一:主题

    1.题目

      把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。

      输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。

    2.思路

      在最开始,我看到这个题目,以为就是使用遍历,然后百度了一下,原来里面还有玄机。

      首先,就是考虑的是时间复杂度,重要的特性就是人家为啥弄一个旋转数组,要考虑。

      和二分查找一样,我们left和right分别指向数组的第一个元素和最后一个元素。

      如果中间元素大于第一个元素,那么最小值应该在后一部分,我们left = mid。如果中间元素小于最后一个元素,那么最小值应该在前一部分,我们right = mid。以此查找最小元素。

      注意:需要注意一种特殊的情况是,原本的排序就是有序的。我们令初始的中间指针mid指向第一个元素。
      另外还有一种情况就是,当三个指针 right, leftmid 均相同时,如下图所示,我们无法断定前后那一部分包含最小值,此时只能用顺序查找算法。

    3.程序

      这里使用两种方式。

     1 package first;
     2 
     3 /**
     4  * 旋转数组中的最小数
     5  */
     6 public class MinNumberInRotateArray {
     7 
     8     public static void main(String[] args){
     9         int[] num={3,4,5,1,2};
    10         //方式一
    11         int minNum=getNum(num);
    12         System.out.println("==="+minNum);
    13         //方式二
    14         int minNum2=getNum(num);
    15         System.out.println("==="+minNum2);
    16     }
    17 
    18     /**
    19      * 直接进行比遍历,然后时间复杂度是n
    20      */
    21     public static int getNum(int[] num){
    22         int j=0;
    23         for(int i=0;i<num.length-1;i++){
    24             if(num[i]>num[i+1]){
    25                 j=i+1;
    26                 break;
    27             }
    28         }
    29         return num[j];
    30     }
    31 
    32     /**
    33      * 使用二分查找的方式,时间复杂度更小
    34      */
    35     public static int getNum2(int[] array){
    36         // 如果数组长度为0则返回-1
    37         if (array.length == 0)
    38         {
    39             return -1;
    40         }
    41         int left = 0;
    42         int right = array.length - 1;
    43         int mid = left;
    44         // 当最左边值大于等于最右边时候
    45         while (array[left] >= array[right])
    46         {
    47             // 如果此时数组只剩下两个数值
    48             if (right - left == 1)
    49             {
    50                 // 最小的就是右边
    51                 mid = right;
    52                 break;
    53             }
    54             // 如果数组长度是2个以上
    55             mid = (left + right) / 2;
    56             // 假如最左边和中间以及最右边值都相等,只能进行顺序查找,如{1,1,1,0,1}
    57             if (array[left] == array[mid] && array[left] == array[right])
    58                 return orderFind(array, left, right);
    59             // 如果最左边小于等于中间,说明最小值在后半部分,把mid位置标记为最左侧如{3,4,5,1,2}
    60             if (array[mid] >= array[left])
    61                 left = mid;
    62                 // 如果最左侧大于等于中间值,说明最小值在前半部分,把mid位置标记为最右侧{4,5,1,2,3}
    63             else if (array[mid] <= array[left])
    64                 right = mid;
    65         }
    66         return array[mid];
    67     }
    68 
    69     public static int orderFind(int[] array, int left, int right)
    70     {
    71         int min = array[left];
    72         for (int i = left + 1; i <= right; i++)
    73         {
    74             if (array[i] < array[left])
    75                 min = array[i];
    76         }
    77         return min;
    78     }
    79 
    80 }

    4.时间复杂度

      直接遍历时间复杂度:O(n)

      二分查找的时间复杂度更小:O(log2n)

    5.参考

      https://blog.csdn.net/qq_38087131/article/details/104878657

  • 相关阅读:
    “做”的“累”
    举国默哀三天
    AjaxRequest
    客户端表单验证js
    书籍下载链接
    Html元素动态添加方法
    java文件读写操作
    查看oracle当前session
    转一篇有关Java的内存泄露的文章(受益哦)
    《高效能人士的七个习惯》摘录
  • 原文地址:https://www.cnblogs.com/juncaoit/p/10251194.html
Copyright © 2020-2023  润新知