目录
我是按照代码随想录的刷题顺序的,以此记录下自己的学习进展 + 感悟
今天刷的是 二分查找,每次通过mid来找target。
一、704. 二分查找
二分查找的关键确实是 不变量,确定好 left 和 right的变化。可以明确一个概念,left和right都是边界,通过什么循环条件在升序list查找target呢?这是一个关键,对边界的判断。每次通过 mid对 left和right进行变化,可以明确,一旦left 大于 right,就是没找到,循环退出。
循环条件就是:
while left <= right:
循环里面是三个分支,mid - 1和+1 是因为if条件,mid左边小,右边大。
if nums[middle] < target:
left = middle + 1
elif nums[middle] > target:
right = middle - 1
else:
return middle
其他要注意的就是,卡哥说的两种写法了。
二、35.搜索插入位置
插入位置,要求判断 target不再list中,应该放在哪?
跟进了这道题,就稍微理解,left都right都是用来做边界的,不要用mid来做了
由于 target不再list中,直接跳出循环,按照第一种写法,left 大于 right,可以确定的是,这时候 left = right + 1 , left,也就是左边界,就是要找的位置。找到的时候,mid = left + right // 2,mid = right = left
三、34. 在排序数组中查找元素的第一个和最后一个位置
这一题对二分查找的,边界,有着更明确的要求。
- 情况一:target 在数组范围的右边或者左边,例如数组{3, 4, 5},target为2或者数组{3, 4, 5},target为6,此时应该返回{-1, -1}
- 情况二:target 在数组范围中,且数组中不存在target,例如数组{3,6,7},target为5,此时应该返回{-1, -1}
- 情况三:target 在数组范围中,且数组中存在target,例如数组{3,6,7},target为6,此时应该返回{1, 1}
问题本质可以理解通过,二分法来确定 左右边界,怎么确定。这里用了两个思路
1、rightBoder = -2 # 因为-2在list中位置没有定义,为了target不在list情况做了方便
2、target在左区间,左边界时左边第一个找到的。可以理解下如
nums = [2,3,5,6] target = 2
这个情况下,right和mid不断向left逼近,直到 list[mid] = target时,表示找到了。mid右边的数比mid大,mid左边的数比mid小。找到的时候,left = right + 1,mid = right
if nums[middle] >= target: # 寻找左边界,nums[middle] == target的时候更新right
right = middle - 1;
leftBoder = right;
else:
left = middle + 1