search for a range(找出一个数在数组中开始和结束位置)
Given an array of integers 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]
.
For example,
Given [5, 7, 7, 8, 8, 10]
and target value 8,
return [3, 4]
.
这一题是从一个有序数组中找出一个数的开始位置和结束位置。这个题目跟求数组中一个数的个数一样(出现次数)。
平常的做法,直接遍历 ,复杂的是O(n),因为有序,用二分查找。复杂度为O(logn)。
像这种查找,因为有重复数字,可以分两步。
1,找出target,如果有多个,求出第一次出现的那个(有序以后)。
2,找出最后一次出现的那个。
如果求个数,则两者相减。。所以这两个步骤都要掌握。
见下面的标记。。一定记住
class Solution { public int[] searchRange(int[] nums, int target) { int[] result=new int[2]; if(nums==null||nums.length==0){ result[0]=-1; result[1]=-1; return result; } int left=0; int right=nums.length-1; //查找最左边的位置 while(left<right){ int mid=(left+right)/2; if(nums[mid]>target) right=mid-1; else if(nums[mid]<target) left=mid+1; else right=mid; //这一步。。求最最左边的,当相等时,将右指针移到mid上 } if(nums[left]!=target){ //用left是因为:当存在这样的数时,left=right了,一样;不存在时,right可能到-1,所以用left。 result[0]=-1; result[1]=-1; return result; } result[0]=left; //查找最右边位置 left=0;right=nums.length-1; while(left<right){ int mid=(left+right+1)/2; //这一步,重点之一 if(nums[mid]>target) right=mid-1; else if(nums[mid]<target) left=mid+1; else left=mid; //这一步。 }
//因为上面已经确保了存在,所以这里不需要再判断 result[1]=right; //用right是因为:当存在这样的数时,left=right了,一样;不存在时,left可能到length,所以用right。 return result; } }