LeetCode 热题 HOT 100 Java题解
34. 在排序数组中查找元素的第一个和最后一个位置
题目:
给定一个按照升序排列的整数数组 nums
,和一个目标值 target
。找出给定目标值在数组中的开始位置和结束位置。
你的算法时间复杂度必须是 O ( l o g n ) O(log n) O(logn) 级别。
如果数组中不存在目标值,返回 [-1, -1]
。
示例:
输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]
二分查找,相等情况处理
O ( l o g n ) O(logn) O(logn)级别一定是二分查找,这个题目是要找左右边界,因此最重要的一点是要在中值等于目标值时如何处理,以下代码都是按照左闭右闭区间进行处理的,利用flag来处理相等时向左还是向右。
迭代版本:
class Solution {
public int binarySearch(int[] nums, int target, boolean flag){
int lo = 0;
int hi = nums.length - 1;
while(lo <= hi) {
int mid = lo + (hi - lo) / 2;
if(nums[mid] > target || (flag && nums[mid] == target)){
hi = mid - 1;
}else {
lo = mid + 1;
}
}
return lo;
}
public int[] searchRange(int[] nums, int target) {
if(nums.length == 1 && nums[0] == target) return new int[] {0,0};
int left = binarySearch(nums, target, true);
int right = binarySearch(nums, target,false) - 1;
if(left < 0 || left >= nums.length || nums[left] != target) {
left = -1;
right = -1;
}
return new int[] {left, right};
}
}
递归版本
class Solution {
public int binarySearch(int[] nums, int left, int right, int target, boolean flag){
if (left > right) return left;
int mid = (right - left) / 2 + left;
if(nums[mid] > target || (flag && nums[mid] == target)) return binarySearch(nums, left, mid - 1, target, flag);
else return binarySearch(nums, mid + 1, right, target, flag);
}
public int[] searchRange(int[] nums, int target) {
if(nums.length == 1 && nums[0] == target) return new int[] {0,0};
int left = binarySearch(nums, 0, nums.length - 1, target, true);
int right = binarySearch(nums, 0, nums.length - 1, target,false) - 1;
if(left < 0 || left >= nums.length || nums[left] != target) {
left = -1;
right = -1;
}
return new int[] {left, right};
}
}
复杂度分析
-
时间复杂度: O ( l o g n ) O(logn) O(logn)
二分查找,复杂度为 O ( l o g n ) O(logn) O(logn)。
-
空间复杂度: O ( 1 ) O(1) O(1)
迭代空间复杂度为 O ( 1 ) O(1) O(1),递归由于栈的开销复杂度为 O ( l o g n ) O(logn) O(logn)。