704. 二分查找
个人比较习惯用左闭右开的写法,这次看了视频以后更加理解了左闭右闭、左闭右开两种写法的原理,以前还不太理解加不加等号、要不要减一等问题,其实关键是要保持循环不变量(就是要一直保持区间左闭右开或左闭右闭)。
代码如下:
def search(nums, target):
l = 0
r = len(nums) # 左闭右开区间:[l, r)
while l < r: # 要保持区间合法,故不加等号,l == r时,区间无效
mid = (l+r) // 2
if target > nums[mid]:
l = mid + 1 # 已明确target比mid值大,且左侧为闭,因此从mid+1开始查找,[left+1,mid)
elif target < nums[mid]:
r = mid # target比mid小,而右侧为开,因此右端为mid,[left, mid)
else:
return mid
return -1
27.移除元素
第一次接触快慢指针的题目,只能勉强写一个暴力的解法,但是也遇到了不少问题。
首先要注意的是,数组的元素再内存地址中是连续的,所以不能单独删除数组中的某一个元素,只能覆盖。也就是让要删去元素后面的元素全部前移。
1. 暴力解法
def removeElement(nums, val):
size = len(nums)
i = 0
while i < size: # 只能用while写,因为后面i要减1,for的话减1就无效了
if nums[i] == val:
for j in range(i, size-1): # size要减1,否则会越界
nums[j] = nums[j+1]
size -= 1
i -= 1 # 后面的元素都前移了,所以i也要前移一个,不然会遗漏一个
i += 1
return size
2. 双指针
设置fast、slow两个指针,用一层循环实现两个循环的功能。要先明确两个指针各自的作用。
fast:查找新数组中将要添加的元素(即不需要被删除的元素)
slow:更新新数组元素的下标
def removeElement(self, nums, val):
fast = 0
slow = 0
size = len(nums)
for i in range(size):
if nums[i] != val:
nums[slow] = nums[fast] # 不需要被删除的元素赋给slow
slow += 1 # 当元素不需要删除时,slow指针前移
fast += 1 # fast指针要一直前移
return slow
参考来自代码随想录:
二分查找文章讲解:代码随想录
视频讲解:手把手带你撕出正确的二分法 | 二分查找法 | 二分搜索法 | LeetCode:704. 二分查找_哔哩哔哩_bilibili
移除元素文章讲解:代码随想录
视频讲解:数组中移除元素并不容易! | LeetCode:27. 移除元素_哔哩哔哩_bilibili
加油!