这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战
leetcode 搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 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
解题:从一个排序数组中查询一个目标值,虽然使用暴力循环遍历也可以查询到,但是题目还要求了时间复杂度,所以也不能简单的直接使用暴力循环了,很明显的可以使用二分查找可以快速的查找到目标值,但是题目还有一个要求的是当查找不到目标值时不是返回不存在,而是返回目标值应该按顺序插入数组中的位置,其实同样也可以使用二分查找。当目标值不存在数组中时,应当插入到数组的位置就是第一个大于目标值的位置下标;那么当目标值存在数组中时,数组中查找到的位置就应该是等于目标值的位置下标。所以二分查找就可以转换为查找第一个大于等于目标值target的位置下标,最终改造基本二分查找法的代码,不断缩小查询的范围区间来找到第一个大于等于目标值的位置下标。同时还有种特殊情况,当数组元素都比目标值大或者小的时候,可以提前判断直接返回对应的0或者数组长度,这样也算稍微优化一下。具体的定义left、right两个指针代表二分查找的范围区间,循环条件就是left和right相遇就结束,取left+right的中间值mid下标去跟目标值target判断,如果大于等于目标值,说明应该到[left,mid]区间继续查找,否则就缩小left范围继续查找,最后返回left位置的下标就可以了。
class Solution {
public int searchInsert(int[] nums, int target) {
if (nums[0] > target) {
return 0;
}
if (nums[nums.length - 1] < target) {
return nums.length;
}
int left = 0;
int right = nums.length;
while (left < right) {
int mid = (left + right) >> 1;
if (target <= nums[mid]) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
}