Leetcode 34. 在排序数组中查找元素的第一个和最后一个位置

85 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情

1.题目

给你一个按照非递减顺序排列的整数数组 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]

2.思路

本题需要我们找到数组中目标值出现的第一个位置和最后一个位置,对于这种要求,我们可以直接考虑进行一次遍历然后判断每个数是否为目标值,并将目标值的位置记录下来保存到数组中,然后将数组的第一个和最后一个值返回就得到了结果,但是题目对时间复杂度有要求,对于我们这种办法时间复杂度为On就显得不合适了。

这个时候我们考虑到题目中的非递减顺序排列,就说明数组中的内容已经完成了排序,那么我们只需要找到第一个目标值以及第一个大于目标值的位置这样我们就能得到目标位置了。

首先我们判断如果数组第一个值大于目标值或者最后一个值小于目标值,那就说明数组中没有目标值。然后我们开始循环直到起始指针大于末尾指针,或者我们已经找到目标值的位置了。然后利用二分法先计算中间位置,然后判断与目标值的大小比较,然后考虑在左右半区继续执行,直到最后找到目标值

3.代码

var searchRange = function(nums, target) {
    let res = [-1, -1]
    let  len = nums.length
    let  left = 0
    let  right = len - 1
    while (left <= right) {
        let mid = left + Math.floor((right - left) / 2);
        
        if (nums[mid] === target && (mid === len - 1 || nums[mid + 1] > target)) {
        res[1] = mid;
        break;
        }
        
        if (nums[mid] <= target) {
        left = mid + 1;
        } else {
        right = mid - 1;
        }
    }
    left = 0;
    while (left <= right) {
        let mid = left + Math.floor((right - left) / 2);
        if (nums[mid] === target && (mid === 0 || nums[mid - 1] < target)) {
        res[0] = mid;
        break;
        }
        
        if (nums[mid] >= target) {
        right = mid - 1;
        } else {
        left = mid + 1;
        }
    }
    
    return (res[0] === -1 || res[1] === -1) ? [-1, -1] : res;
};