携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情
题目描述
原题链接 :
35. 搜索插入位置 - 力扣(LeetCode) (leetcode-cn.com)
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 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
提示:
- 1 <= nums.length <= 10^4
- -10^4 <= nums[i] <= 10^4
- nums 为 无重复元素 的 升序 排列数组
- -10^4 <= target <= 10^4
思路分析
二分的关键:
- 考虑清楚进行二分要找的是什么
- 永远去思考下一轮搜索应该在哪个区间里
技巧:
- 简单问题,只需要用到mid,使用[left, right] + <=
- 复杂问题,需要循环后再判断,使用[left, right) + <
- if中:题目要我们找符合条件a的元素,我们就对条件a取反面,这样分析不容易出错
思路一:
找到第一个大于等于target的元素 [left,right),二分的过程找第一个大于等于target的元素
二分结束后,left==right,left、right所指即是第一个大于等于target的元素
AC 代码
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
#[left,right)
left = 0
right =len(nums)
#nums[mid]小于target,去[mid+1,right)找第一个大于等于target的元素
#nums[mid]大于等于target,区间向左收缩,去[left,mid)中找找mid前面还有没有大于等于target的元素
while left < right:
mid = (left + right) // 2
if nums[mid] < target:
left = mid + 1
else:
right = mid
#最终 left==right 是第一个大于等于taget的元素
return left