题目链接

​35. 搜索插入位置​

题目

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

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

示例

  • 示例 1
//输入: nums = [1,3,5,6], target = 5
//输出: 2
  • 示例 2
//输入: nums = [1,3,5,6], target = 2
//输出: 1
  • 示例 3
//输入: nums = [1,3,5,6], target = 7
//输出: 4
  • 示例 4
//输入: nums = [1,3,5,6], target = 0
//输出: 0
  • 示例 5
//输入: nums = [1], target = 0
//输出: 0
  • 提示:
1 <= nums.length <= 10⁴
-10⁴ <= nums[i] <= 10⁴
nums 为无重复元素的升序排列数组
-10⁴ <= target <= 10⁴

方法解答

暴力破解

一般来讲,关于数组方面的题目一般都会有暴力破解的方法,基本上流程如下

  • 判断数组的边界条件
  • for循环遍历,target依次跟数据元素比较,输出值
  • 针对特殊情况,进行单独判断输出

代码如下

public static int searchInsert(int[] nums, int target) {
//判断nums的边界情况
if (nums == null || nums.length == 0) {
return -1;
}
int n = nums.length;
for (int i = 0; i < n ; i++) {
//如果数组的值大于等于target,直接返回,该数组的index
if (nums[i] >= target) {
return i;
}
}
//遍历完成后,target大于数组最后一位的值,直接返回数组的长度。
return n;
}

虽然暴力破解方法基本适用于所有的数组问题,但是根据题目要求时间复杂度必须要​​O(log n)​​,很明显暴力破解的时间复杂度是O(n),可以知道主要考察的二分查找方法的使用。

二分查找

二分查找基本上就有一套模版,流程如下

  • 设置左侧下标left,右侧下标rught
  • 通过while循环,计算中间下表mid
  • 根据nums[mid] 和 target 之间的大小进行判断,相等则直接返回下标
  • nums[mid] < target 则 left 右移
  • nums[mid] > target 则 right 左移
  • 查找结束如果没有相等值则返回 left,该值为插入位置

代码如下

public static int searchInsert(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return -1;
}
int l = 0;
int r = nums.length - 1;
while (l <= r) {
int mid = (l + r) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] > target) {
r = mid - 1;
} else {
l = mid + 1;
}
}
return l;
}