题目:搜索目标范围
难度: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]的时候,此时继续向右边搜索。。。