0x00 循环不变式
初始化:它在循环的第一轮迭代开始之前,应该是正确的。
保持:如果在某一次循环迭代开始之前是正确的,那么在下一次迭代开始之前,它也应该保持正确(假设当循环变量等于k时符合,再看执行一遍循环体后是否还符合循环不变式)。
终止:循环能够终止,并且可以得到期望的结果。(这一步是和数学归纳法不同的一点,用循环不变式则更进一步,数学归纳法到这里就得出了一个关系式就结束,而用循环不变式,不但要先确保一个正确的关系式,还要看最后循环结束时,循环变量最后等于多少,根据循环不变式推导是否符合自己的要求。)。
只要保障上述三者成立,那么这个循环就是正确的。下列问题全部是在输入数组是升序的情况下讨论。
0x01 准确查找问题
区间为[a, b)
类型。
初始化:我们假设都给定了正确类型的nums
和target
。
保持:当nums[mid] == target
的时候,显然我们找到了target
,我们直接返回mid
即可。当target > nums[mid]
的时候,此时[l, mid]
中的元素全部小于target
,此时target
只会存在于[mid+1, r)
这个区间中。当target < nums[mid]
的时候,此时[mid, r)
这个区间内的元素全部大于target
,此时target
只会存在于[l, mid-1]
区间内,此时为了保障区间类型的统一,我们将[l, mid-1]
变成[l, mid)
。
终止:当l==r
,此时区间[l, r)
中没有元素了,那么target
就不在nums
中。
class Solution:
def find(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
l, r = 0, len(nums)
while l < r:
mid = (l + r)//2
if target == nums[mid]:
return mid
elif target > nums[mid]:
l = mid + 1
else:
r = mid
return -1
区间为[a, b]
类型
初始化:我们假设都给定了正确类型的nums
和target
。
保持:当nums[mid] == target
的时候,显然我们找到了target
,我们直接返回mid
即可。当target > nums[mid]
的时候,此时[l, mid]
中的元素全部小于target
,此时target
只会存在于[mid+1, r]
这个区间中。当target < nums[mid]
的时候,此时[mid, r]
这个区间内的元素全部大于target
,此时target
只会存在于[l, mid-1]
区间内。
终止:当l > r
,此时区间[l, r]
中没有元素了,那么target
就不在nums
中。
class Solution:
def find(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
l, r = 0, len(nums) - 1
while l <= r:
mid = (l + r)//2
if target == nums[mid]:
return mid
elif target > nums[mid]:
l = mi