704. 二分查找
二分查找可以用左右指针法,使用时一定要考虑好搜索区间怎么分。搜索区间怎么分决定了while的终止条件。有两种分法,左闭右闭区间 [left, right] 和左闭右开。
左闭右开
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
n = len(nums)
left = 0
right = n
while (left < right):
mid = left + (right - left) // 2
if target < nums[mid]:
right = mid
elif target > nums[mid]:
left = mid + 1
else:
return mid
return -1
左闭右闭
左闭右闭的时候,right是从列表最后一个值开始,搜索区间一直包含right,所以right = mid -1。while循环时left也是能取到right的。
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
n = len(nums)
left = 0
right = n - 1
while (left <= right):
mid = left + (right - left) // 2
if target < nums[mid]:
right = mid - 1
elif target > nums[mid]:
left = mid + 1
else:
return mid
return -1
注意:
mid = (right + left) // 2
这种写法会发生上溢问题。int 占用 4 字节,32 比特,数据范围为:-2147483648 ~ 2147483647
[-2^31 ~ 2^31-1]
那么对于两个都接近
2147483647
的数字而言,它们相加的结果将会溢出,变成负数
链接:https://juejin.cn/post/7145742873009324040
27. 移除元素
暴力解法
class Solution(object):
def removeElement(self, nums, val):
"""
:type nums: List[int]
:type val: int
:rtype: int
"""
n = len(nums)
i = 0
while i < n:
if val == nums[i]:
j = i
while j < n-1:
nums[j] = nums[j+1]
j+=1
n -= 1
i -= 1
i+=1
return n
用for i in range遍历时是没法改i的值的。
双指针法(快慢指针法)
快指针指向当前处理的元素,判断nums[fast]是否等于val。慢指针指着确定好的输出数组的元素。 如果判断为true,慢指针不动,快指针处理下一个。如果为false, 快指针指向的元素赋到左指针,然后两个指针一起右移。
def removeElement(self, nums, val):
n = len(nums)
slow = 0
fast = 0
for fast in range(n):
if nums[fast] != val:
nums[slow] = nums[fast]
slow+=1
return slow