1. 二分查找
1.1 二分查找中while的区间问题
二分查找要注意区间的开闭问题,从而来判断比较区间的时候是否要包含.
在左闭右闭区间中,[left, right], left和right可以同时取到,所以应该是
while(left <= right)
而在左闭右开区间中,显然left和right无法同时取到,所以应该是
while(left < right)
1.2 二分查找中区间划分是否包含middle
在左闭右闭区间中
if(num[middle] > target):
right = middle - 1
elif (num[middle] < target):
left = middle + 1
显然,在num[middle] > target时,我们需要更新左区间的右边界,由于是一个左闭右闭的区间,那么右边的值是包含的,又因为我们已经通过条件得知middle的值不为target. 所以在下次搜索区间中就不需要middle,所以right更新为middle -1.
同理,num[middle] < target时, left的值更新为middle + 1
在左闭右开的区间中
num[middle] < target时, 和左闭右闭的情况类似,left的值应该更新为middle + 1
而因为right是开区间,所以取值的时候取不到right,所以right的值更新为middle. right = middle
1.3其他一些注意事项
middle = left + (right - left) // 2
middle = (left + right) // 2
这两种写法似乎没有本质差别,但是第一种写法可以防止数据溢出,所以这样写比较好
2.数组删除元素
2.1 暴力求解法
先用for循环数组,再用for遍历,将后面一位的值赋予给前一位
这里注意for i in range(a,b)是包含a但不包含b的, 所以有两种写法
for j in range(i, n-1):
nums[j] = nums[j+1]
或者
for j in range(i+1, n):
num[j-1] = nums[j]
注意在每个覆盖操作之后,更新数组长度,即n -= 1
2.2 双指针
设置一个快指针和一个慢指针,快指针记录新数组所需要的元素,慢指针记录新数组元素的下标值.
快指针遍历到每一个不需要删除的元素,就把元素值赋予给慢指针,更新数组
fast总是递增的,因为它需要检查数组里面的每一个元素
slow只是在找到一个不需要删除的元素时才递增
n = len(nums)
i = 0
fast = 0
slow = 0
while fast<n:
if nums[fast] != val:
nums[slow] = nums[fast]
slow += 1
fast += 1
return slow
- 当
nums[fast]
不等于val
时:- 把
nums[fast]
的值赋给nums[slow]
。这步操作实质上是将有效元素(即不等于val
的元素)移动到数组的前端。 - 然后
slow
指针增加 1,这表示下一个不等于val
的元素应该放置的新位置。
- 把
- 不论
nums[fast]
是否等于val
,fast
指针总是增加 1。这是因为快指针的责任是遍历整个数组,检查每一个元素。
好处是只需要一次遍历,时间复杂度为O(n)