#!D:\softwares\anaconda python
# -*- coding: utf-8 -*-
# @Time : 2020/12/7 15:17
# @Author : weweaq
# @Site :
# @File : 35_搜索插入位置.py
# @Software: PyCharm
from typing import List
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums)
while left < right:
middle = (left + right) // 2
if target == nums[middle]:
return middle
elif target > nums[middle]:
left = middle + 1
else:
right = middle
return right
solution = Solution()
print(solution.searchInsert([1,3,5,6], 10))
""" 暴力解法,遍历并进行判断,基础!
普通:
def searchInsert(self, nums: List[int], target: int) -> int:
for num in nums:
if num >= target:
return nums.index(num)
return len(nums)
较好: 要在二分查找的过程中,保持不变量,这也就是「循环不变量」,所谓循环不变量,是指循环中一直要保证为真的量
这个二分查找中,保持左闭右闭的区间,所以循环不变量为[left, right], 左或者右需要为 middle-1 或者 middle+1
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums) - 1
while left <= right: # 此处如果缺失等于号,就会丢失 【a,a】这个区间,处理target小于Min(nums)或者大于max(nums)时,
# 会出错,提前跳出 while ,返回错误的 right
middle = (left + right) // 2
if target == nums[middle]:
return middle
elif target > nums[middle]:
left = middle + 1
else:
right = middle - 1
return right+1
这个二分查找中,保持左闭右开的区间,所以循环不变量为[left, right), 左需要为 middle+1,右需要为 middle
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums) # 因为要保持循环不变量,这里一开始得是 len(nums), WCNMDP, 我看了半个多小时才发现这里的不同,一直都
# 以为这里和上面一样不需要改变 是 right = len(nums) - 1 ,所以结果一直都不对,纠结了贼长时间!
while left < right:
middle = (left + right) // 2
if target == nums[middle]:
return middle
elif target > nums[middle]:
left = middle + 1
else:
right = middle
return right
重点:在左闭右开区间的二分法中,我感觉二分法确实很神奇,他其实对于 target 的比较,并不是会与两边的 nums[left] or nums[right] 有关
,它是一直都与 nums[median] 进行比较(即只与中位值进行比较,不与边界值进行比较),所以 left 和 right 索引在必要时是可以超出数组
长度的界限,我觉得很有意思!
注意:第二个二分查找中,保持左闭右开的区间,所以循环不变量为[left, right),在初始化时就要满足这个条件,right = len(nums)!!
"""
"""
以下供单链表使用:
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = None
class LinkList:
def __init__(self):
self.head_node = self.tail = self.head = None
def initList(self, data):
self.head = ListNode(data[0])
self.tail = self.head
for i in data[1:]:
self.tail.next = ListNode(i)
self.tail = self.tail.next
return self.head
def printList(self, head):
if head is None:
return
self.head_node = head
while self.head_node is not None:
if self.head_node.next is not None:
print(self.head_node.val, end=' => ')
else:
print(self.head_node.val)
self.head_node = self.head_node.next
"""