学过二分查找了,一开始先写了个递归的版本,时间复杂度O(logN),空间复杂度O(logN)。
def halfsearch(self,nums: List[int], target: int,left:int,right:int) -> int:
mid=(left+right)//2
if left+1==right:
return -1
else:
if nums[mid]==target:
return mid
elif nums[mid]>target:
return Solution().halfsearch(nums,target,left,mid)
else:
return Solution().halfsearch(nums,target,mid,right)
效果肉眼可见地差,于是改成迭代版本,把空间复杂度优化为O(N)
class Solution:
def search(self, nums: List[int], target: int) -> int:
left=-1
right=len(nums)
while(left+1-right):
mid=(left+right)//2
if nums[mid]==target:
return mid
elif nums[mid]>target:
right=mid
else:
left=mid
return -1
事实上,代码的时间效率和空间效率都大大提高了。
另一方面,代码随想录分享了两种对数组的处理思路:分割为左闭右闭和左闭右开区间,但我本人惯用的方法是左开右开的处理,应该是无伤大雅,运行下来也没有出现问题。
没什么思路,第一反应是:直接调用remove函数不就行了,事实上直接就通过了。
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
while True:
try:
nums.remove(val)
except:
break
return len(nums)
看完随想录分析才知道题目学习的是双指针算法,于是重写得到:
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
slow=fast=0
while fast<len(nums):
if nums[fast]!=val:
nums[slow]=nums[fast]
slow+=1
fast+=1
return slow
时间复杂度O(N),空间复杂度与题设要求一致为O(1)
写的过程中怀疑了一下len(nums)会不会随着循环而改变,才想明白双指针其实是将数组中不包括val的数移动到数组头上,后面的元素个数fast-slow = val在数组中的个数