给定一个按照升序排列的整数数组 nums
,和一个目标值 target
。找出给定目标值在数组中的开始位置和结束位置。
你的算法时间复杂度必须是 O(log n) 级别。
如果数组中不存在目标值,返回 [-1, -1]
。
示例 1:
输入: nums = [5,7,7,8,8,10]
, target = 8
输出: [3,4]
示例 2:
输入: nums = [5,7,7,8,8,10]
, target = 6 输出: [-1,-1]
------------------
思路:
这题主要要求时间复杂度是O(log n), 所以对于一个排好序的数组,第一时间想到 二分法查找。
步骤:1、先用二分法查找,找到一个target,作为一个基准点mid。
2、从mid往左,二分法查找,找到最左边缘
3、从mid往右,二分法查找,找到最右边缘
如果不用二分法查找,那就从左右两头往中间靠拢查找,复杂度为O(n)
public int[] searchRange(int[] nums, int target) { int[] res = new int[2]; int mid = binarySearch(nums, target, 0, nums.length - 1); if (mid == -1) { res[0] = -1; res[1] = -1; return res; } int left = searchRangeLeft(nums, target, 0, mid - 1); int right = searchRangeRight(nums, target, mid + 1, nums.length - 1); if (left == -1) { res[0] = mid; } else { res[0] = left; } if (right == -1) { res[1] = mid; } else { res[1] = right; } return res; } private int binarySearch(int[] nums, int key, int start, int end) { //返回查到的下标 if (start > end) { return -1; } int mid = (start + end) / 2; if (nums[mid] == key) { return mid; } else if (nums[mid] > key) { return binarySearch(nums, key, start, mid - 1); } else { return binarySearch(nums, key, mid + 1, end); } }
//往左查找 private int searchRangeLeft(int[] nums, int target, int start, int end) { if (start > end) { //退出递归条件 return -1; } int mid = (start + end) / 2; if (nums[mid] == target) { //命中,继续从mid往左寻找:1.若未找到,返回mid 2.若找到,返回找到的下标 return searchRangeLeft(nums, target, start, mid - 1) == -1 ? mid : searchRangeLeft(nums, target, start, mid - 1); } else {//未命中,从mid往右找 return searchRangeLeft(nums, target, mid + 1, end); } } //往右查找 private int searchRangeRight(int[] nums, int target, int start, int end) { if (start > end) { //退出递归条件 return -1; } int mid = (start + end) / 2; if (nums[mid] == target) {//命中,继续从mid往右寻找。1.若未找到,返回mid 2.若找到,返回找到的下标 return searchRangeRight(nums, target, mid + 1, end) == -1 ? mid : searchRangeRight(nums, target, mid + 1, end); } else {//未命中, 从mid 往左找 return searchRangeRight(nums, target, start, mid - 1); } }