704.二分查找
关键在于区间的选取,可以选择左闭右闭或者左闭右开
左闭右闭
因为两边都是闭区间都可以取到,因此在nums[mid]>target
的时候,需要把right = mid - 1
,因此时的mid
是一定无法取等号的,所以改变范围的时候需要对其减一。同时在判定结束条件的时候需要用while(left<=right)
,因为left=right
是有意义的。
class Solution:
def search(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums) - 1
while(left<=right):
mid = (left+right)//2
if target<nums[mid]:
right = mid - 1
elif target> nums[mid]:
left = mid + 1
else:
return mid
return -1
左闭右开
由于右边变成了开区间,即右索引不会被取到,当target<nums[mid]
的时候需要把right=mid
,另外结束条件变成while(left<right)
,还有需要注意的是初始化right
的时候赋值为len(nums)
,如果和左闭右闭一样的话则一开始就舍弃了数组最右边的值
class Solution:
def search(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums)
while(left<right):
mid = (left+right)//2
if target<nums[mid]:
right = mid
elif target> nums[mid]:
left = mid + 1
else:
return mid
return -1
35.搜索插入位置
使用二分查找,不同处在于如果值不存在于数组中需要返回其插入的位置。在二分查找结束之后多一步比较,在这里使用左闭右闭的写法,如果nums[left]<val
则插入位置为left+1
,反之为left
class Solution:
def div_serach(self, nums, val):
left = 0
right = len(nums)
while(left <= right):
mid = (left + right)//2
if nums[mid]>val:
right = mid - 1
elif nums[mid]<val:
left = mid + 1
else:
return mid
if nums[left] > val:
return left
else:
return left + 1
def searchInsert(self, nums: List[int], target: int) -> int:
if target < min(nums):
return 0
elif target > max(nums):
return len(nums)
else:
return self.div_serach(nums, target)
27. 移除元素
暴力解法
双循环,找到值后把后面数组全部往前移一位,同时数组长度和第一个循环的索引减一。非常暴力
双指针法
快慢指针,慢指针指向新数组的末尾,快指针遍历整个数组,如果快指针找到了对应的值,则跳过,否则把快指针的值赋值到慢指针指向的位置并且两者同时加1。
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
i = 0
for j in range(len(nums)):
if nums[j] != val:
nums[i] = nums[j]
i += 1
return i