一、今日任务
- 二分查找 27. 移除元素
二、二分查找
2.1 题目:704.二分查找
2.2 解题过程
二分查找是一个比较简单的查找方法。所以接下来在记录在解题过程中主要遇到的问题。
2.2.1第一个问题就是查找不到时无法退出循环
解决方法是不断修改left、right的初值,temp的计算公式、left、right的更新公式和while循环的条件。
在解题前就应该确定是左闭右闭还是左开右闭。
在解题时,遇到无法退出循环时,都没有修改while的结束条件。
这里总结的出问题原因还是因为对于解题思路的不清晰。
2.2.2结合随想录文章复习整个题解思路
首先确定二分法的前提:list 有序、无重复。
其次两种解题思路:左闭右闭和左开右闭。这两种方法在初始设置、循环条件和更新时要分别满足其基本思路。
左闭右开代码
# 左闭右开
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
index = -1
left = 0
right = len(nums)
while (left < right):
middle = int((left + right) / 2)
if nums[middle] == target:
index = middle
break
elif nums[middle] > target:
right = middle
else:
left = middle + 1
return index
左闭右闭代码
# 左闭右闭
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
index = -1
left = 0
right = len(nums)-1
while (left <= right):
middle = int((left + right) / 2)
if nums[middle] == target:
index = middle
break
elif nums[middle] > target:
right = middle - 1
else:
left = middle + 1
return index
三、移除元素
3.1 27. 移除元素
3.2 解题过程
题目要求:不额外使用数组空间
这题还是耽误了很久。
第一个原因是题目看出了,应该是移出给定值,而不是保留。这导致思路错乱了很久。
以下是解题代码:
def removeElement(self, nums, val):
"""
:type nums: List[int]
:type val: int
:rtype: int
"""
left = 0
right = len(nums) - 1
while right >= 0 and nums[right] == val:
right -= 1
if right < 0:
return left
while left <= right:
if nums[left] == val:
nums[left] = nums[right]
nums[right] = val
right -= 1
left += 1
while right >= 0 and nums[right] == val:
right -= 1
if right < 0:
break
return left
使用的是左右指针,右指针始终指向一个保留数字,左指针扫描,出现移出数字,与右指针交换,更新指针。
3.3与随想录解题的差距
随想录中给出了暴力解法、快慢指针法和双向指针法(比自己的解法更加简洁清晰和通用)
暴力解法:从左到右扫描,出现要移除的值,移出,更新数组。
length = len(nums)
i = 0
# 在range(0,length)中,范围会被固定,所以改用while
while i < length:
if nums[i] == val:
for j in range(i+1,length):
nums[j-1] = nums[j]
i -= 1
length -= 1
i += 1
return length
快慢指针法:从两个从0开始的指针,快指针寻找第一个满足条件的值,与慢指针交换,慢指针加1(即确定新数组的第一个位置是谁),快指针继续找,知道快指针遍历完。
# 快慢指针
fast = 0 # 快指针
slow = 0 # 慢指针
size = len(nums)
while fast < size: # 不加等于是因为,a = size 时,nums[a] 会越界
# slow 用来收集不等于 val 的值,如果 fast 对应值不等于 val,则把它与 slow 替换
if nums[fast] != val:
nums[slow] = nums[fast]
slow += 1
fast += 1
return slow
双向指针:左边找最近的移除值,右边找最近的保留值,如果左在左,右在右交换。
left = 0
right = len(nums) - 1
while left <= right:
while left <= right and nums[right] == val:
right -= 1
while left <= right and nums[left] != val:
left += 1
if left < right :
nums[left] = nums[right]
nums[right] =val
left += 1
right -= 1
return left