1 题目地址
2 题目说明
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例 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
3 解题思路
目标值对应的位置可能会有四种情况:
1、目标值在数组所有元素之前
2、目前值等于数组中的某一个元素
3、目标值插入数组中的位置
4、目标是在数据中的所有元素之后
基于这4种情况可以思考代码上如何实现。
暴力方式:遍历数组,从小到大遍历去查找第一个大于等于目标值的位置,则是待插入的位置(情况1 2 3都符合)。 情况4直接对应nums.length即可。
二分查找:定义left right,每次拿middle=(left+right)/2跟目标值比较, 相等则直接返回索引位置,如果大于target则向左移动(right=middle-1),如果是小于target则向右移动(left=middle+1),当left>=right退出循环,right+1则为返回的位置。
二分查找法过程:【左闭右闭】
二分查找法过程:【左闭右开】
4 代码编写
4.1 暴力方式
按数组从左到右依次遍历:找到一个大于target的索引下标,循环内要是找不到就是在数组的最后
class Solution {
public int searchInsert(int[] nums, int target) {
for (int i=0; i<nums.length; i++) {
// 分别处理如下三种情况
// 目标值在数组所有元素之前
// 目标值等于数组中某一个元素
// 目标值插入数组中的位置
if (nums[i]>=target) { // 一旦发现大于或者等于target的num[i],那么i就是我们要的结果
return i;
}
}
// 目标值在数组所有元素之后的情况
return nums.length; // 如果target是最大的,或者 nums为空,则返回nums的长度
}
}
4.2 二分法实现
每次都以中间的数据跟目标数据比较,直到找到对应的目标位置
class Solution {
public int searchInsert(int[] nums, int target) {
for (int i=0; i<nums.length; i++) {
// 分别处理如下三种情况
// 目标值在数组所有元素之前
// 目标值等于数组中某一个元素
// 目标值插入数组中的位置
if (nums[i]>=target) { // 一旦发现大于或者等于target的num[i],那么i就是我们要的结果
return i;
}
}
// 目标值在数组所有元素之后的情况
return nums.length; // 如果target是最大的,或者 nums为空,则返回nums的长度
}
}
4.2.1 二分法[left,right]
[left,right],左闭右闭,左右数值都是有效的,当left=right也是有效的
class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0;
int right = nums.length-1;
while(left<=right) {
int middle = (left+right)/2;
if (nums[middle] > target) {
right = middle - 1; // 目标值在左区间
} else if (nums[middle] < target) {
left = middle + 1; // 目标值在右区间
} else {
return middle;
}
}
// 分别处理如下四种情况
// 目标值在数组所有元素之前 [0, -1]
// 目标值等于数组中某一个元素 return middle;
// 目标值插入数组中的位置 [left, right],return right + 1
// 目标值在数组所有元素之后的情况 [left, right], 因为是右闭区间,所以 return right + 1
return right + 1;
}
}
4.2.2 二分法[left,right)
[left,right],左闭右开,左数值是有效的,右数值是无效的,当left=right是无效的
class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0;
int right = nums.length;
while(left<right) {
int middle = (left+right)/2;
if (nums[middle] > target) {
right = middle; // 目标值在左区间, 右区间是开
} else if (nums[middle] < target) {
left = middle + 1; // 目标值在右区间
} else {
return middle;
}
}
// 分别处理如下四种情况
// 目标值在数组所有元素之前 [0, -1]
// 目标值等于数组中某一个元素 return middle;
// 目标值插入数组中的位置 [left, right],return right + 1
// 目标值在数组所有元素之后的情况 [left, right], 因为是右闭区间,所以 return right + 1
return right;
}
}