LeetCode35、搜索插入位置

75 阅读1分钟

LeetCode 系列记录我学习算法的过程。

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

题目

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

示例:

输入: nums = [1,3,5,6], target = 5
输出: 2


输入: nums = [1,3,5,6], target = 2
输出: 1


输入: nums = [1,3,5,6], target = 7
输出: 4

提示

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums 为 无重复元素 的 升序 排列数组
  • -104 <= target <= 104

思路

根据题目及示例,可知给定的数组是一个升序的数组,需在这个升序数组中找到目标值或其插入的位置

仔细观察不难发现,其答案有两种情况,一种是存在该值,返回其索引即可

另一种即不存在,需找到插入的位置,在这升序数组里只要找到第一个比该值大的数组项索引即是插入位置

如果没有比它大的值,那就插入数组最后一项

代码实现

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var searchInsert = function(nums, target) {
    // 数组长度
    const len = nums.length
    // 最后一项都小于目标值 则直接返回数组长度
    if (nums[len - 1] < target) return len
    // 从头遍历数组
    for(let i = 0; i < len; i++) {
        // 只要遍历项大于或等于目标值,则返回当前项的索引
        if (nums[i] >= target) {
            return i
        }
    }
};

简单题做起来就是舒服,轻松通过

image.png

优化

我使用的方法比较简单,也是常见的暴力解法,这题还可以使用二分法,每次都找中间项来进行比较

每次比较后排除一半的值,查找速度会快上不少

var searchInsert = function(nums, target) {
    let left = 0; // 左指针
    let right = nums.length; // 右指针
  
    // 当左右指针相遇后结束循环
    while (left <= right) {
        // 找中间项索引
        const mid = Math.floor((left + right) / 2);
        // 如果中间项值小于目标值,移动左指针
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            // 如果中间项值大于目标值,移动右指针
            right = mid - 1;
        } else {
            // 如果中间项值等于目标值,返回改索引
            return mid;
        }
    }
    // 最后返回左指针的值
    return left;
};

image.png