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的第一个数

所以当A[mid]<=target的时候,此时应该向左边继续搜寻

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

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

猜你喜欢

转载自www.cnblogs.com/Xieyang-blog/p/8999367.html