• LeetCode第[34]题(Java):Search for a Range


    题目:搜索目标范围

    难度:Medium

    题目内容

    Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value.

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

    If the target is not found in the array, return [-1, -1].

    翻译

    给定一个按升序排序的整数,找到给定目标值的起始和结束位置。

    您的算法的运行时复杂性必须按照O(log n)的顺序。

    如果在数组中找不到目标,返回[-1,-1]。

    我的思路:数组、有序、查找、lgn————》二分法

        找到后用两个指针向两边移动,直到不等于,就是他的范围。

    MyCode

     1     public int[] searchRange(int[] nums, int target) {
     2         if (nums.length == 0) {
     3             return new int[]{-1,-1};
     4         }
     5         int loc = binaryFind(nums, target);
     6         if (loc == -1) {
     7             return new int[]{-1,-1};
     8         }
     9         int start = loc;
    10         int end = loc;
    11         while (start-1 > -1 && nums[start-1] == nums[loc])
    12             start--;
    13         while (end+1 < nums.length && nums[end+1] == nums[loc])
    14             end++;
    15         return new int[]{start, end};
    16     }
    17     
    18     static int binaryFind(int[] nums, int target) {
    19         int low = 0;
    20         int high = nums.length - 1;
    21         while (low <= high) {
    22             int mid = low + (high - low)/2;
    23             if (nums[mid] == target) {
    24                 return mid;
    25             } else if (nums[mid] > target) {
    26                 high = mid - 1;
    27             } else {
    28                 low = mid + 1;
    29             }
    30         }
    31         return -1;
    32     }

    我的复杂度:O(logN)+ O(N) = O(N)

    因为后面的双向移动确实有可能将所有元素进行一次遍历,所以达不到O(logN)级别

    编码过程中出现问题

    1、length 写成了 lengh;

    2、high的初始值设置成了length,应该为length-1;

    3、 while(start-1 > -1 && nums[start-1] == nums[loc])  注意这个写法,如果将start--放入此处判断,那么最后的值就多减了1;

    4、没找到的时候别忘了return [-1,-1]。

    答案代码

     1     public int[] searchRange(int[] A, int target) {
     2         int start = Solution.firstGreaterEqual(A, target);
     3         if (start == A.length || A[start] != target) {
     4             return new int[]{-1, -1};
     5         }
     6         return new int[]{start, Solution.firstGreaterEqual(A, target + 1) - 1};
     7     }
     8 
     9     private static int firstGreaterEqual(int[] A, int target) {
    10         int low = 0, high = A.length;
    11         while (low < high) {
    12             int mid = low + ((high - low) >> 1);
    13             //A[low] <= target < A[high]
    14             if (A[mid] < target) {
    15                 low = mid + 1;
    16             } else {
    17                 high = mid;
    18             }
    19         }
    20         return low;
    21     }

    答案复杂度:O(logN)

    答案思路:在二分法的基础上做出了改进,即最后返回大于等于target的第一个数(所有target里最左边的那一个)

    所以不仅当target>A[mid],并且target==A[mid]的时候,此时都应该向左边继续搜寻

    但是此时是令high = mid,而不是mid-1,是因为A[mid]<=target的时候,包括了A[mid]==target,此时如果取high = mid-1,则有可能将唯一的一个target给弄到右边去

    最后得到start,然后再将方法的target给+1再传入此方法,那么就能找到target右边的那一个数字的下标。

    举个例子:

    [1,2,3,5,5,9],target=5

    首先定位到下标2——3,因为3<target,要找的点必定在右边:lo=mid+1

    再定位下标4——5,因为5>=target,所以也要向左寻找:high=mid

    。。。

    扩展:我们也可以求的小于等于target的第一个数,即所有target最右边的那个数,那么当target>=A[mid]的时候,此时继续向右边搜索。。。

  • 相关阅读:
    Json解析
    Nopcommerce 使用Task时dbcontext关闭问题
    Webview离线功能(优先cache缓存+cache缓存管理)
    Android按钮单击事件的四种常用写法
    xUtils 源码解析
    返回键的复写onBackPressed()介绍
    GBK、GB2312和UTF-8编码区分
    Android 动画之RotateAnimation应用详解
    Android getWidth和getMeasuredWidth的区别
    WebView三个方法区别(解决乱码问题)
  • 原文地址:https://www.cnblogs.com/Xieyang-blog/p/8999367.html
Copyright © 2020-2023  润新知