[LeetCode 35] 搜索插入位置(Python+二分查找问题总结)

目录

    • 题目描述
    • 解题思路
        • 二分查找
    • 代码实现
    • Tips

题目描述

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

示例 1:

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

示例 2:

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

题目链接:
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-insert-position

解题思路

二分查找

最后的目标:在一个有序数组中找第一个大于等于 target \textit{target} target 的下标。

问题转化到这里,直接套用二分法即可,即不断用二分法逼近查找第一个大于等于 target \textit{target} target 的下标 。

复杂度分析

  • 时间复杂度: O ( log ⁡ n ) O(\log n) O(logn),其中 n n n 为数组的长度。二分查找所需的时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn)

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

代码实现

class Solution(object):
    def searchInsert(self, nums, target):
        n = len(nums)
        if target > nums[-1]:
            return n
        left, right = 0, n-1
        ans = -1
        while left <= right:
            mid = (left + right) // 2
            if target <= nums[mid]:
                right = mid - 1
                ans = mid
            else:
                left = mid + 1
        return ans

Tips

  • 二分查找的思想:
    减而治之,即将大规模问题转化成小规模问题。减而治之是分而治之的特例,将大问题划分成若干个子问题以后,最终答案只在其中一个子问题里。

  • 如何避免死循环(重难点)?
    根据 mid 被分到左边区间还是右边区间,代码写出来只有以下 2 种:
    边界收缩行为 1: mid 被分到左边。即区间被分成 [left, mid][mid + 1, right],这里用「闭区间」表示区间端点可以取到。
    边界收缩行为 2: mid 被分到右边。即区间被分成 [left, mid - 1][mid, right]

    面对上面的边界收缩行为 2(mid 被分到右边),在待搜索区间收缩到只剩下 2 个元素的时候,就有可能造成死循环。搜索区间不能缩小,是造成死循环的原因。
    所以要把上面「边界收缩行为」对应的中间数取法补上。
    [LeetCode 35] 搜索插入位置(Python+二分查找问题总结)_第1张图片

    边界收缩行为 1: mid 被分到左边。即区间被分成 [left, mid] 与 [mid + 1, right],此时取中间数的时候下取整。
    mid = left + (right - left) / 2
    边界收缩行为 2: mid 被分到右边。即区间被分成 [left, mid - 1] 与 [mid, right],此时取中间数的时候上取整。
    mid = left + (right - left + 1) / 2

    记住下面这条规则:在 if else 语句里面只要出现 left = mid 的时候,把去中间数行为改成上取整即可。
    [LeetCode 35] 搜索插入位置(Python+二分查找问题总结)_第2张图片
    参考链接:
    LeetCode上的一个很优秀的题解+总结


A u t h o r : C h i e r Author: Chier Author:Chier

你可能感兴趣的:(有事没事刷刷oj)