文章目录
- 题目
- 方法一:二分查找(先找到mid,在根据mid确定左右区间)
- 方法二:分两次二分查找,一次用于找左区间,一次用于找右区间
题目
方法一:二分查找(先找到mid,在根据mid确定左右区间)
- 第一步先找到target所在的位置mid
- 在根据mid 在数组左右分两个while循环找左右区间,一旦nums[mid] != target,就返回mid值
- 最后查找位置会停在区间外的一个位置,需要矫正回来
// 方法一 :二分法找目标元素的位置,然后在目标元素的位置的左右找左右区间public int[] searchRange(int[] nums, int target) {if(nums.length == 0) return new int[]{-1,-1};int mid = search( nums, target);//二分法找target位置if(mid == -1) return new int[]{-1,-1};//若没有 直接返回 - 1 - 1int m = mid;while(m < nums.length){//根据mid 去找右区间最大下标if(nums[m] != target) break;m ++;}int n = mid;while(n >=0){//根据mid 去找左区间最小下标if(nums[n] != target) break;n--;}return new int[]{n+1,m-1};//最终m其实是在右区间后面一个位置停止的 m需要-1 同理最终实是在左区间前面一个位置停止的,n需要+1}//二分法找目标元素 目标元素不存在返回 - 1public int search(int[] nums, int target){int left = 0 ;int right = nums.length - 1 ;while(left <= right){int mid = (right - left)/2 + left;if(nums[mid] == target) return mid;if(nums[mid] > target) right = mid -1;if(nums[mid] < target) left = mid +1;}return -1;}
方法二:分两次二分查找,一次用于找左区间,一次用于找右区间
一定要结合画图来理解
// 方法二 :二分法来去寻找左右边界public int[] searchRange(int[] nums, int target) {if(nums.length == 0) return new int[]{-1,-1};int left = leftjoin(nums,target);int right = rightjoin(nums,target);// 情况一if (left == -2 || right == -2) return new int[]{-1, -1};// 情况三if (right - left > 1) return new int[]{left + 1, right - 1};// 情况二return new int[]{-1, -1};}//寻找左边界public int leftjoin(int[] nums, int target){int left = 0;int right = nums.length -1;int leftjoin = -2;//记录左边界的赋值情况while(left <= right){int mid = left + (right -left);if(nums[mid] >= target){right = mid -1;leftjoin = right;}else {left = mid + 1;}}return leftjoin;}//寻找右边界public int rightjoin(int[] nums, int target){int left = 0;int right = nums.length -1;int rightjoin = -2;//记录左边界的赋值情况while(left <= right){int mid = left + (right -left);if(nums[mid] > target){right = mid -1;}else {left = mid + 1;rightjoin = left;}}return rightjoin;}
参考题解:34. 在排序数组中查找元素的第一个和最后一个位置