携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第23天,点击查看活动详情
前言
今天的题目为中等,利用二分查找能够解决,并且只需要进行一次就可以通过第一次的结果去查找另一个目标,节省时间复杂度。
每日一题
今天的题目是 34. 在排序数组中查找元素的第一个和最后一个位置,难度为中等
-
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
-
如果数组中不存在目标值 target,返回 [-1, -1]。
-
你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。
示例 1:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
示例 2:
输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]
示例 3:
输入:nums = [], target = 0
输出:[-1,-1]
提示:
- 0 <= nums.length <= 105
- -109 <= nums[i] <= 109
- nums 是一个非递减数组
- -109 <= target <= 109
题解
二分查找
题目给出一个有序的数组,并且要求去这个数组中查找某一个值,在时间复杂度为 O(logn) 的条件下,首先想到的就是二分查找,通过二分查找,我们能够找到数组当中最接近目标值的那个元素,并且通过优先给左边的指针进行位移,并且排除掉和目标值相等的这种情况,能够控制在多个目标值的时候,拿到最左边的目标值。
并且在拿到多个相同的目标值的最左边的值的时候,我们就不需要再次去查找最右边的值,因为数组是有序的,我们直接按位往下查找相同的目标值,一直到不同为止。
并且数组中可能会出现不存在目标的情况,所以最后确定下来的指针还需要判断一下是否是目标值,不是的话返回 [-1,-1]。
function searchRange(nums: number[], target: number): [number, number] {
let l = -1
let r = nums.length
while (l + 1 != r) {
let mid = Math.floor((l + r) / 2)
if (nums[mid] < target)
l = mid
else
r = mid
}
let left = r
let right = r
while (nums[right] == target) {
right++
}
if (nums[left] != target) return [-1, -1]
return [left, right - 1]
};