Python算法提升
此开源图书由ithaiq原创,创作不易转载请注明出处
基础算法
二分搜索
模板
from typing import List
def search(nums: List[int], target: int) -> int:
l, r = 0, len(nums)-1
while l <= r:
mid = l+(r-l)//2
if nums[mid] < target:
l = mid+1
elif nums[mid] > target:
r = mid-1
else:
return mid
return -1
def search(nums: List[int], target: int) -> int:
start, end = 0, len(nums)-1
while start + 1 < end:
mid = start + (end - start) // 2
if nums[mid] < target:
start = mid
else:
end = mid
if nums[start] == target:
return start
elif nums[end] == target:
return end
else:
return -1
给定一个包含 n 个整数的已排序数组,要求找出给定目标值 target 的起始和结束位置。如果目标值不在数组中,则返回 [-1, -1]。
解题思路:关键是要找到目标值 target 在数组中第一次出现和最后一次出现的位置,因此可以利用两次二分搜索分别找到第一次和最后一次的位置。
def searchRange(A: List[int], target: int) -> List[int]:
if len(A) == 0:
return [-1, -1]
result = [-1, -1]
start = 0
end = len(A) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if A[mid] > target:
end = mid
elif A[mid] < target:
start = mid
else:
end = mid
# 搜索左边的索引
if A[start] == target:
result[0] = start
elif A[end] == target:
result[0] = end
else:
return result
start = 0
end = len(A) - 1
while start + 1 < end:
mid = start + (end - start) // 2
if A[mid] > target:
end = mid
elif A[mid] < target:
start = mid
else:
start = mid
# 搜索右边的索引
if A[end] == target:
result[1] = end
elif A[start] == target:
result[1] = start
return result
编写一个高效的算法来判断一个 m x n 的矩阵中是否存在目标值。该矩阵具有如下特性:
每行的元素从左到右按升序排列。
每行的第一个元素大于前一行的最后一个元素。
def searchMatrix(matrix: List[List[int]], target: int) -> bool:
# 思路:将二维数组转为一维数组进行二分搜索
if not matrix or not matrix[0]:
return False
row: int = len(matrix)
col: int = len(matrix[0])
start: int = 0
end: int = row * col - 1
while start + 1 < end:
mid: int = start + (end - start) // 2
# 获取二维数组对应值
val: int = matrix[mid // col][mid % col]
if val > target:
end = mid
elif val < target:
start = mid
else:
return True
if matrix[start // col][start % col] == target or matrix[end // col][end % col] == target:
return True
return False
给定 n 个版本号 [1, 2, ..., n],要找出导致之后所有版本出错的第一个错误的版本。可以通过调用
bool isBadVersion(version)
函数来判断版本号version
是否出错。实现一个函数来查找第一个错误的版本。尽量减少对调用 API 的次数。
def firstBadVersion(n: int) -> int:
# 思路:二分搜索
start: int = 1
end: int = n
while start + 1 < end:
mid: int = start + (end - start) // 2
if isBadVersion(mid):
end = mid
elif not isBadVersion(mid):
start = mid
if isBadVersion(start):
return start
return end
寻找数组中经过旋转后的最小元素。假设数组在预先未知的某个点上进行了旋转(例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2])(数组中不存在重复的元素)
def findMin(nums: List[int]) -> int:
# 思路:将最后一个值作为target,然后往左移动,最后比较start、end的值
if not nums:
return -1
start: int = 0
end: int = len(nums) - 1
while start + 1 < end:
mid: int = start + (end - start) // 2
# 最后一个元素值为 target
if nums[mid] <= nums[end]:
end = mid
else:
start = mid
if nums[start] > nums[end]:
return nums[end]
return nums[start]
寻找数组中经过旋转后的最小元素。假设数组在预先未知的某个点上进行了旋转(例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2])(包含重复元素)
def findMin(nums: List[int]) -> int:
# 思路:跳过重复元素,mid值和end值比较,分为两种情况进行处理
if not nums:
return -1
start: int = 0
end: int = len(nums) - 1
while start + 1 < end:
# 去除重复元素
while start < end and nums[end] == nums[end - 1]:
end -= 1
while start < end and nums[start] == nums[start + 1]:
start += 1
mid: int = start + (end - start) // 2
# 中间元素和最后一个元素比较(判断中间点落在左边上升区,还是右边上升区)
if nums[mid] <= nums[end]:
end = mid
else:
start = mid
if nums[start] > nums[end]:
return nums[end]
return nums[start]
假设一个按照升序排序的数组在未知位置上进行了旋转(例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2])。现在需要搜索给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1。(数组中不存在重复的元素)。
def search(nums: List[int], target: int) -> int:
# 思路:两条上升直线,四种情况判断
if not nums:
return -1
start: int = 0
end: int = len(nums) - 1
while start + 1 < end:
mid: int = start + (end - start) // 2
# 相等直接返回
if nums[mid] == target:
return mid
# 判断在哪个区间,可能分为四种情况
if nums[start] < nums[mid]:
if nums[start] <= target <= nums[mid]:
end = mid
else:
start = mid
elif nums[mid] < nums[end]:
if nums[mid] <= target <= nums[end]:
start = mid
else:
end = mid
if nums[start] == target:
return start
elif nums[end] == target:
return end
return -1
假设一个按照升序排序的数组在未知位置上进行了旋转(例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2])。现在需要搜索给定的目标值,判断给定的目标值是否存在于数组中。(数组中存在重复的元素)。
def search(nums: List[int], target: int) -> bool:
# 思路:两条上升直线,四种情况判断,并且处理重复数字
if not nums:
return False
start: int = 0
end: int = len(nums) - 1
while start + 1 < end:
# 处理重复数字
while start < end and nums[start] == nums[start + 1]:
start += 1
while start < end and nums[end] == nums[end - 1]:
end -= 1
mid: int = start + (end - start) // 2
# 相等直接返回
if nums[mid] == target:
return True
# 判断在哪个区间,可能分为四种情况
if nums[start] < nums[mid]:
if nums[start] <= target <= nums[mid]:
end = mid
else:
start = mid
elif nums[end] > nums[mid]:
if nums[mid] <= target <= nums[end]:
start = mid
else:
end = mid
if nums[start] == target or nums[end] == target:
return True
return False
排序算法
快速排序
def QuickSort(nums: List[int]) -> List[int]:
quickSort(nums, 0, len(nums)-1)
return nums
def quickSort(nums: List[int], start: int, end: int) -> None:
if start < end:
pivot = random.randint(start, end)
nums[end], nums[pivot] = nums[pivot], nums[end]
left, right = partition(nums, start, end)
quickSort(nums, start, left)
quickSort(nums, right, end)
def partition(nums: List[int],start:int,end:int)->Tuple[int, int]:
pivot = nums[end]
left,right=start,end-1
i=left
while i<=right:
if nums[i]<pivot:
nums[i],nums[left]=nums[left],nums[i]
left+=1
i+=1
elif nums[i]>pivot:
nums[i],nums[right]=nums[right],nums[i]
right-=1
else:
i+=1
nums[left],nums[end]=nums[end],nums[left]
return left-1,right+1
动态规划
数据结构
二叉树
链表
栈和队列
算法思维
递归思维
滑动窗口
二叉搜索树
回溯法
最后更新于