每日一道算法Day21

82 阅读1分钟

题目描述:

image.png

题目中最重要的两点信息:

  1. nums为无重复元素的升序数组。
  2. 使用时间复杂度为O(log n)的算法。

从题目可以得知这又是一道二分法的题目, 基本思路比较简单, 需要注意的是一些边界情况。 代码如下:

function searchInsert(nums: number[], target: number): number {
  if(nums.length === 0) return 0;
//定义左右双指针
  let left = 0;
  let right = nums.length - 1;
  
  /*
  重点: 这里和以往不同, 采用的是 left < right, 而不是 left <= right
  
  */
  while (left < right) {
    const mid = Math.floor((left + right) / 2);
    if (nums[mid] === target) {
    //因为数组无重复元素, 所以相等的情况直接返回索引
      return mid;
    }
    if (nums[mid] < target) {
    //中间值小于目标值的情况, 继续从数组左半部分开始寻找
      left = mid + 1;
    } else if (nums[mid] > target) {
    //中间值大于目标值的情况, 继续从数组右半部分开始寻找
      right = mid - 1;
    }
  }
  /*
   这里是数组中没有找到 target 的情况
   如果当前 左侧指针值大于 target, 则返回 left
   为什么要加等于呢? 等于情况不是while中能遇到么?
   当数组长度小于2时, 是不会进入while循环的..最开始便漏掉了这个边界情况
  */
  if (nums[left] >= target) return left;
  /**
  如果当前 左侧指针值小于 target, 则返回 left + 1
  */
  return left + 1;
}

递归版本(需要调整方法参数):

function searchInsert(nums: number[], target: number, start: number = 0, end: number = nums.length - 1): number {
  if(nums.length === 0) return 0;
  if (end - start < 1) {
    if (nums[start] >= target) {
      return start;
    }
    return start + 1;
  }

  const mid = Math.floor((start + end) / 2);
  if (nums[mid] === target) return mid;

  return nums[mid] > target
    ? searchInsert(nums, target, start, mid - 1)
    : searchInsert(nums, target, mid + 1, end);
}