一、题目描述

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

你可以假设数组中无重复元素。

示例 1:

输入: [1,3,5,6], 5

输出: 2

示例 2:

输入: [1,3,5,6], 2

输出: 1

示例 3:

输入: [1,3,5,6], 7

输出: 4

示例 4:

输入: [1,3,5,6], 0

输出: 0

二、解题思路

暴力破解

遍历数组,当元素大于等于目标值的时候,返回其索引,假如目标值比数组所有元素都大,返回nums.length

public class Solution {
public int searchInsert(int[] nums, int target) {
int i=0;
while(i<nums.length){
if(nums[i]>=target){
return i;
}else{
i++;
}
}
return i;
}
}

复杂度分析

时间复杂度:O(n),一次遍历。

空间复杂度:O(1),只需要常数空间存放若干变量。

二分法

首先,插入位置有可能在数组的末尾(题目中的示例 3),需要单独判断。如果在数组的末尾,插入位置的下标就是数组的长度;

否则,根据示例和暴力解法的分析,插入位置的下标是 大于等于 target 的第 1个元素的位置。

因此,严格小于 target 的元素一定不是解,在循环体中将左右边界 left 和 right 逐渐向中间靠拢,最后 left 和 right 相遇,则找到了插入元素的位置。

public class Solution {
public int searchInsert(int[] nums, int target) {
int len = nums.length;
if (len == 0) {
return 0;
}
// 特判
if (nums[len - 1] < target) {
return len;
}
int left = 0;
int right = len - 1;
while (left < right) {
int mid = left + (right - left) / 2;
// 严格小于 target 的元素一定不是解
if (nums[mid] < target) {
// 下一轮搜索区间是 [mid + 1, right]
left = mid + 1;
} else {
// 下一轮搜索区间是 [left, mid]
right = mid;
}
}
return left;
}
}

复杂度分析

时间复杂度: O(logn) ,其中 n 为数组的长度,在循环一次排除一半,因此时间复杂度是对数级别的。

空间复杂度:O(1),只需要常数空间存放若干变量。

欢迎关注微信公众号【算法攻城师】

Leetcode No.35 搜索插入位置(二分法)_二分法