• LeetCode第[33]题(Java):Search in Rotated Sorted Array


    题目:在翻转有序中搜索

    难度:Medium

    题目内容

    Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

    (i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).

    You are given a target value to search. If found in the array return its index, otherwise return -1.

    You may assume no duplicate exists in the array.

    Your algorithm's runtime complexity must be in the order of O(log n).

    翻译

    假设一个按升序排序的数组在事先不知道旋转点的情况下翻转。

    (即。0,1,2,4,5,6,7可能变成4,5,6,7,0,1,2)。

    您获得了搜索的目标值。如果在数组中找不到它的索引,否则返回-1。

    数组中不存在重复。

    您的算法的运行时复杂度应该为O(log n)

    我的思路:要复杂度O(log n),但是数组只是基本有序,而排序算法的最佳情况也要O(N),本弱鸡想不出什么很好方法。。。

         那就强行上吧,先插入排序一波,再二分法搜索。

         然而最后要返回下标,再排序后下标会发生变化,所以再新建一个数组存储下标,在排序过程中,此数组相应的值跟着一起移动。

    MyCode

     1     public int search(int[] nums, int target) {
     2         int[] index = new int[nums.length];
     3         for (int i = 0; i < nums.length; i++) {
     4             index[i] = i;
     5         }        
     6         insertSort(nums, index);
     7         return binaryFind(nums, target, index);
     8     }
     9     
    10     static int binaryFind(int[] nums, int target, int[] index) {
    11         int low = 0;
    12         int high = nums.length - 1;
    13         while (low <= high) {
    14             int mid = low + (high - low)/2;
    15             if (nums[mid] == target) {
    16                 return index[mid];
    17             } else if (nums[mid] > target) {
    18                 high = mid - 1;
    19             } else {
    20                 low = mid + 1;
    21             }
    22         }
    23         return -1;
    24     }
    25     
    26     static void insertSort(int[] nums, int[] index) {
    27         for (int i = 1; i < nums.length; i++) {
    28             int temp = nums[i];
    29             int temp2 = index[i];
    30             int j = i - 1;
    31             while (j > -1 && nums[j] > temp) {
    32                 nums[j+1] = nums[j];
    33                 index[j+1] = index[j];
    34                 j--;
    35             }
    36             nums[j+1] = temp;
    37             index[j+1] = temp2;
    38         }
    39     }

    我的算法复杂度:O(N2),因为插入排序的最坏情况就是O(N2)。

    编码过程中出现的问题

    1、把插入排序的逻辑给忘了。。

    答案代码

     1     public int search(int[] A, int target) {
     2         int n = A.length;
     3         int lo=0,hi=n-1;
     4         while(lo<hi){
     5             int mid=(lo+hi)/2;
     6             if(A[mid]>A[hi]) lo=mid+1;
     7             else hi=mid;
     8         }
     9         int rot=lo;
    10         lo=0;hi=n-1;
    11         while(lo<=hi){
    12             int mid=(lo+hi)/2;
    13             int realmid=(mid+rot)%n;
    14             if(A[realmid]==target)return realmid;
    15             if(A[realmid]<target)lo=mid+1;
    16             else hi=mid-1;
    17         }
    18         return -1;
    19     }

    答案复杂度:O(logN)

    答案思路:首先利用数组局部仍然有序的特点,和 A[mid]>A[hi] 的条件,以二分法定位到最小的那一个值的下标,注意当 A[mid]<=A[hi] 的时候,应该是hi=mid,因为此时的mid有可能就是最小点,所以不能放过。【当要求的点不是直接定位的mid的时候(等循环结束),mid 有可能就是最终的值,下一层的 lo 和 hi 的取值不能都把mid排除, 其中一个就是mid

    找到最小点后,记录下来,然后继续对原数组进行二分法搜索,然而,参与比较的mid应该改成realMid=(mid+rot)%n

    以[4,5,6,7,0,1,2]为例,找到最小值(真起点)0的下标4后,取mid=(0+6)/2 = 3,而真正的中点下标应该等于(mid+rot)%n = (3+4)%7 = 0

    之后的向左右移动是一样的,所以还是变化mid的值即可。

  • 相关阅读:
    ubuntu16.04下docker安装和简单使用(转)
    spring security There was an unexpected error (type=Forbidden, status=403).
    笔记42 Spring Web Flow——Demo(2)
    Idea debug时报错:Command line is too long
    特殊字符(包括emoji)梳理和UTF8编码解码原理(转)
    如何理解多租户架构?(转)
    Android Studio使用阿里云Aliyun Maven仓库
    解决 INSTALL FAILED CONFLICTING PROVIDER
    Android解决冲突
    Mysql查询库、表存储量(Size)
  • 原文地址:https://www.cnblogs.com/Xieyang-blog/p/8999737.html
Copyright © 2020-2023  润新知