leetcode:search_insert_position偏移法、Pythonic、二分法

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

示例 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
"""

方法一: 偏移法

第一想到的是利用下标偏移,与每个元素进行比较,如果相等则返回下标,如果target比当前的数小,那么它将会被插入在当前位置,也就是当前数的下标(因为根据题目,nums是有序的)。

from typing import List
class Solution:
    # 类似指针法,从前往后,一个一个对比,时间复杂度O(n)
    def searchInsert(self, nums: List[int], target: int) -> int:
        index = 0
        len_nums = len(nums)
        while index < len_nums:
            if target == nums[index] or target < nums[index]:
                return index
            index += 1
        return len_nums

方法二:Pythonic

题目中比较关键的一点是“如果目标值不存在于数组中,返回它将会被按顺序插入的位置。”,如果没有这个,通过 nums.index(target) 一行代码就可以了,所以我想到的是,如果nums中没有就把target添加进入后,然后再找。(感觉使用了Python一些内置的方法,都不适合锻炼算法思维)

# 利用Python的in,若没有找到,就放到nums中排序,再返回target下标
def searchInsert1(self, nums: List[int], target: int) -> int:
    if target in nums:
        return nums.index(target)
    nums.append(target)
    nums.sort()
    return nums.index(target)

方法三:二分法

在有序数组中查找插入元素的位置,显然可以使用二分查找。在循环的过程中,不断排除不需要的解,最后剩下的那个元素就一定是我们想要的。

把需要的目标值留在最后判断,在循环体内不断地把不符合题目要求的子区间排除掉,在退出循环以后,因为只剩下 1 个数没有看到,它要么是目标元素,要么不是目标元素,单独判断即可。

这里正好可以通过下标来迎合题目要求,也无需判断最后一个剩余的原始是否是目标元素,只要剩下一个元素,那么我只要它的下标即可。

# 二分法,看了别人写的思路,然后默写
def searchInsert2(self, nums: List[int], target: int) -> int:
    left, right = 0, len(nums) - 1
    while left <= right:  # 想了下,为啥要加=号,通过debug才发现
        mid = (left + right) >> 1
        mid_var = nums[mid]
        if mid_var == target:
            return mid
        elif mid_var < target:
            left = mid + 1
        else:
            right = mid - 1
    return left

当然还有一种方法,就是先把target放进nums中,这样不用排除不符合的元素了,这种情况下使用二分法,会更容易理解和写代码。

我们平常写程序,定位问题其实通常也用的是这个思路。在适当的地方做一些代码输出,在一些地方打断点来debug,逐步缩小范围,最后找到了有 bug 的那一行或几行代码。

二分法 Reference


这边也复习了一个不常用的小知识点:位运算符

要计算某个整数除以2(或者2的幂次)得到整数,
使用位运算符:mid = (left + right) >> 1
而不必这样做:mid = int((left + right) / 2)

  • << 左移动运算符:运算数的各二进位全部左移若干位,由 << 右边的数字指定了移动的位数,高位丢弃,低位补0。
  • >> 右移动运算符:把">>"左边的运算数的各二进位全部右移若干位,>> 右边的数字指定了移动的位数。
发布了87 篇原创文章 · 获赞 43 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_31362767/article/details/105304541