「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战」。
题目描述🌍
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 的算法。
示例 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
提示:
- <=
nums.length<= - <=
nums[i]<= nums为无重复元素的升序排列数组- <=
target<=
二分搜索插入(左闭右闭)🔎
解题思路
⭐该解法(左闭右闭)最关键的地方在于:为什么返回
left而不是right?!(针对情况(2))
(1)如果要插入的值在数组中,那该值在数组中的位置就是搜索插入的位置,也就是「二分查找」过程。
(2)如果要插入的值不在数组中,那可以分开讨论,但要明确一点,使用左闭右闭插入的话,在最后一次的循环过程中一定会形成以下状态(执行到 int middle = left + (right - left) / 2;):
然后接下来就是判断语句,判断 target(图中 y) 与 nums[middle](图中 x) 的关系,分为两种情况:
y < xy > x
一图胜千言。可见两种情况下,搜索插入的位置都是
left指向的位置。
代码
Java
class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int middle = left + (right - left) / 2;
if (target < nums[middle]) {
right = middle - 1;
} else if (target > nums[middle]) {
left = middle + 1;
} else {
return middle;
}
}
// 两种情况下, left皆为结果!
return left;
}
}
C++
class Solution {
public:
int searchInsert(vector<int> &nums, int target) {
int left = 0;
int right = nums.size() - 1;
while (left <= right) {
int middle = left + (right - left) / 2;
if (target < nums[middle]) {
right = middle - 1;
} else if (target > nums[middle]) {
left = middle + 1;
} else {
return middle;
}
}
return left;
}
};
时间复杂度:,二分查找所需的时间复杂度。
空间复杂度:
二分搜索插入(左闭右开)🔍
解题思路
⭐该解法(左闭右开)就比较容易解决了,因为循环退出的时候
left等于right,且所以return left或return right都可以(针对待插入的值不存在于数组中这种情况)
但该搜索插入方法有一个特殊情况:当 target > nums[length - 1] 时,此时退出循环后,left 与 right 都为 length - 1,而应该返回的值为 length,所以该情况要排除。
代码
Java
class Solution
public int searchInsert(int[] nums, int target) {
// 有且仅有 target > nums[length - 1] 这类情况对该(左闭右开)解法不适用,直接判断即可..
int length = nums.length;
if (target > nums[length - 1]) {
return length;
}
int left = 0;
int right = nums.length - 1;
int middle;
while (left < right) {
middle = left + (right - left) / 2;
if (target < nums[middle]) {
right = middle;
} else if (target > nums[middle]) {
left = middle + 1;
} else {
return middle;
}
}
// return left/right 都可以!
return right;
}
}
C++
class Solution {
public:
int searchInsert(vector<int> &nums, int target) {
int length = nums.size();
// special circumstance
if (target > nums[length - 1])
return length;
int left = 0;
int right = length - 1;
while (left < right) {
int middle = left + (right - left) / 2;
if (target < nums[middle]) {
right = middle;
} else if (target > nums[middle]) {
left = middle + 1;
} else {
return middle;
}
}
// left or right is ok
return right;
}
};
时间复杂度:,二分查找所需的时间复杂度。
空间复杂度:
知识点🌓
本文如有不懂的地方,建议翻阅我上一篇发布的文章:带你领略「二分查找」的魅力
最后🌅
该篇文章为 「LeetCode」 系列的 No.9 篇,在这个系列文章中:
- 尽量给出多种解题思路
- 提供题解的多语言代码实现
- 记录该题涉及的知识点
👨💻争取做到 LeetCode 每日 1 题,所有的题解/代码均收录于 「LeetCode」 仓库,欢迎随时加入我们的刷题小分队!