[路飞]_程序员必刷力扣题: 34. 在排序数组中查找元素的第一个和最后一个位置

「这是我参与2022首次更文挑战的第20天,活动详情查看:2022首次更文挑战

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]
复制代码

暴力破解

思路 由题意知道,需要查找首位和末尾的目标值,那么我们可以在遍历数组nums的过程中,去对比每一个元素是否为target值

具体步骤:

  • 声明结果res = [-1,-1],遍历nums
  • 如果找到target,且res[0] 为-1 ,那么更新res[0] = i 否则只更新res[1]的值即可

最后返回res即可

var searchRange = function(nums, target) {
    var res = [-1,-1]
    for(var i = 0;i < nums.length ; i++){
        if(nums[i]===target){
            if(res[0]===-1){
                res[0] = i
                res[1] = i
            }else{
                res[1] = i
            }
        }
    }
    return res
};
复制代码

二分查找

思路

暴力破解没有利用到nums数组是有序排列的这个条件,其实我们可以用二分查找的方式更快的找到target的位置

具体实现:

  • 声明结果res = [-1,-1],声明left和right为数组两端的两个值
  • while循环条件left<=right,找到重点位置mid
    • 如果nums[mid]小于target那么left = mid+1
    • 如果nums[mid]大于等于target那么right = mid-1

这样循环下去最后left一定会定位在第一个target的位置

但是目标可能有多个值,所以我们需要再次while循环以找到target的末位置

  • while循环条件nums[left] === target,那么我们就可以更新一下res[1]的值,并且left++,往后延伸直到nums[left]不再符合条件

那么此时res中便记录了target的首尾位置信息,返回res即可

var searchRange = function (nums, target) {
    // 二分查找
    var res = [-1, -1]
    var left = 0
    var right = nums.length
    while (left <= right) {
        var mid = (left + right) >> 1
        if (nums[mid] < target) {
            left = mid + 1
        } else {
            right = mid - 1
        }
    }
    // 如果res 不等于[-1,-1] 那么left为target的起始位置
    while (nums[left] === target) {
        if (res[0] === -1) res[0] = left
        res[1] = left
        left++
    }
    return res
};
复制代码

猜你喜欢

转载自juejin.im/post/7062000145067409416