算法挑战61: 在排序数组中查找元素的第一个和最后一个位置

0 阅读2分钟

题目:

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

思路:

学会上一篇的二分查找之和,这道题就简单了

只需要把二分查找的返回值变一下

我们之前那个二分查找是找一个目标值

如果数组中有多个目标值, 那将返回第一个

我们对函数条件稍作修改,就可以使之返回最后一个目标值

然后我们对数组操作两次, 获取到两个索引

还需要判断一下, 如果第一个索引的值大于第二个索引的值, 说明在数组中没有目标值

就返回[-1,-1]就可以了, 也不存在一个为-1的情况,因为找的元素是同一个,要有都有,最多一样罢了,要没有就都没有

最后返回[a,b]


其实不用改造二分查找的函数

只要用这行代码就行,改一下目标值,改成目标值+1,得出结果后再-1

   const end = lowerBound(nums, target + 1) - 1;

代码:

两个二分方法

var searchRange = function (nums, target) {
    let a = binarySearch1(nums, target);
    let b = binarySearch2(nums, target);

    if(a > b){
        a = -1;
        b = -1;
    }

    return [a, b];
};

function binarySearch1(nums, target) {
    let left = 0;
    let right = nums.length;
    while (left <= right) {
        let mid = Math.floor((left + right) / 2);
        if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return left;
}
function binarySearch2(nums, target) {
    let left = 0;
    let right = nums.length;
    while (left <= right) {
        let mid = Math.floor((left + right) / 2);
        if (nums[mid] <= target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return right;
}

一个二分,不同参数方法:

var searchRange = function (nums, target) {
    let a = binarySearch(nums, target);
    let b = binarySearch(nums, target + 1) - 1;

    if (a > b) {
        a = -1;
        b = -1;
    }

    return [a, b];
};

function binarySearch(nums, target) {
    let left = 0;
    let right = nums.length;
    while (left <= right) {
        let mid = Math.floor((left + right) / 2);
        if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return left;
}