leetcode 34题

Posted by franki on June 8, 2021

leetcode 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]

思路

二分法,通过找到第一个等于target的值和找到最后一个等于target的值,即是所求。

代码

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var searchRange = function(nums, target) {
    // 二分搜索变种题(找到第一个等于target的值,找到最后一个等于target的值)
    return [findFirstEqualElement(nums, target), findLastEqualElement(nums, target)];
};

function findFirstEqualElement(nums, target) {
    let low = 0, high = nums.length - 1;
    while (low <= high) {
        const mid = low + (high - low) / 2 | 0;
        if (nums[mid] > target) {
            high = mid - 1;
        } else if (nums[mid] < target) {
            low = mid + 1;
        } else {
            if (mid === 0 || nums[mid-1] !== target) {
                return mid;
            }
            high = mid - 1;
        }
    }
    return -1;
}

function findLastEqualElement(nums, target) {
    let low = 0, high = nums.length - 1;
    while (low <= high) {
        const mid = (high - low) / 2 | 0 + low;
        if (nums[mid] > target) {
            high = mid - 1;
        } else if (nums[mid] < target) {
            low = mid + 1;
        } else {
            if (nums[mid + 1] !== target || mid === nums.length - 1) {
                return mid;
            }
            low = mid + 1;
        }
    }
    return -1;
}

const searchRange = (nums, target) => {
    if (nums.length === 0) {
        return [-1, -1];
    }
    let low = 0, high = nums.length - 1;
    let start = 0, end = 0;
    while (low <= high) {
        const mid = ((high - low) / 2 | 0) + low;
        if (nums[mid] === target) {
            start = mid;
            end = mid;
            while (start > low && nums[start - 1] === nums[start]) {
                start--;
            }
            while (end < high && nums[end+1] === nums[end]) {
                end++;
            }
            return [start, end];
        } else if (nums[mid] > target) {
            high = mid - 1;
        } else {
            low = mid + 1;
        }
    }
    return [-1, -1];
};

复杂度分析:

  • 时间复杂度: O(logN)
  • 空间复杂度:O(1)