leetcode刷题记录-34. 在排序数组中查找元素的第一个和最后一个位置

836 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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]
};

image.png