数组part01
704. 二分查找
注意:
1. 左闭右闭和左闭右开的边界问题
2. middle = left + (left - right) // 2先算left - right,可以避免 left + right 数值过大引起的溢出
class Solution:
def search(self, nums: List[int], target: int) -> int:
# 左闭右闭
left = 0
right = len(nums)-1
while left <= right:
middle = left + (right - left) // 2
if nums[middle] > target:
right = middle - 1
elif nums[middle] < target:
left = middle + 1
else:
return middle
return -1
27. 移除元素
快慢指针:快指针用于判断,慢指针用于记录
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
slow = 0
fast = 0
while fast < len(nums):
if nums[fast] != val:
nums[slow] = nums[fast]
slow += 1
fast += 1
return slow
数组part02
977. 有序数组的平方
双指针相向而行
注意:
1. 初始化result为 res = [float('inf')] * len(nums)
2. 判断标准为left <= right
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
left = 0
right = len(nums) - 1
i = len(nums) - 1
res = [float('inf')] * len(nums)
while left <= right:
if nums[left] ** 2 < nums[right] ** 2:
res[i] = nums[right] ** 2
right -= 1
else:
res[i] = nums[left] ** 2
left += 1
i -= 1
return res
209. 长度最小的子数组
双指针&滑动窗口
注意:
1. 最短长度的初始化:min_length = float('inf')
2. 累加值由右指针开始进行累加,当当前和大于等于目标值时,尝试缩小窗口。先用min_length记录最短长度,再更新累加值,最后更新左指针,顺序不可改变。
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
left = 0
right = 0
cur_sum = 0 # 当前的累加值
min_length = float('inf')
while right < len(nums):
cur_sum += nums[right]
# 当当前和大于等于目标值时,尝试缩小窗口
while cur_sum >= target:
min_length = min(min_length, right - left + 1)
cur_sum -= nums[left]
left += 1
right += 1
return min_length if min_length != float('inf') else 0
59. 螺旋矩阵II
循环不变量
注意:
1. 初始化一个各位为0的n x n矩阵:nums = [[0] * n for _ in range(n)]
2. 行和列的变化与不变的关系
3. n为奇数时,中间会留下一个空,nums[mid][mid] = count
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
nums = [[0]*n for _ in range(n)]
start_x, start_y = 0, 0
loop, mid = n // 2, n // 2
count = 1
for offset in range(1, loop+1):
for i in range(start_y, n-offset):
# 行不变,列在变
nums[start_x][i] = count
count += 1
for i in range(start_x, n-offset):
# 列不变,行在变
nums[i][n-offset] = count
count += 1
for i in range(n-offset, start_y, -1):
# 行不变,列在变
nums[n-offset][i] = count
count += 1
for i in range(n-offset, start_x, -1):
# 列不变,行在变
nums[i][start_y] = count
count += 1
start_x += 1
start_y += 1
if n % 2 != 0:
nums[mid][mid] = count
return nums
其他练习
283. 移动零
快慢指针之后填满0
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
left = 0
right = 0
while right < len(nums):
if nums[right] != 0:
nums[left] = nums[right]
left += 1
right += 1
for i in range(left, len(nums)):
nums[i] = 0
56. 合并区间
Lambda函数,也称为匿名函数,是Python中一种简洁定义单行小函数的方式。Lambda函数本身是一个表达式,它会产生一个函数对象。具体语法,lambda 参数列表: 表达式
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
# 首先,对区间列表按照每个区间的起始位置进行排序
intervals.sort(key=lambda x: x[0])
# 初始化一个空列表,用于存储合并后的区间
merged = []
# 遍历排序后的区间列表
for interval in intervals:
# 如果merged列表为空
# 或者当前区间的起始位置大于merged列表中最后一个区间的结束位置
# 说明当前区间与merged列表中的区间没有重叠
# 可以直接添加到merged列表中
if not merged or merged[-1][1] < interval[0]:
merged.append(interval)
else:
# 如果当前区间与merged列表中的最后一个区间有重叠
# 更新merged列表中最后一个区间的结束位置为两个区间结束位置的较大值
# 这样可以保证合并后的区间是尽可能大的,且不重叠
merged[-1][1] = max(merged[-1][1], interval[1])
# 返回合并后的区间列表
return merged
438. 找到字符串中所有字母异位词
建立dictionary,用list的方式表示。
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
n = len(s)
m = len(p)
if n < m:
return []
s_cnt = [0] * 26
p_cnt = [0] * 26
res = []
# 构造一个长度为m的滑动窗口
for i in range(m):
# 统计p里的字母,记录到list
p_cnt[ord(p[i]) - ord('a')] += 1
# 统计s里的字母,记录到list
s_cnt[ord(s[i]) - ord('a')] += 1
if s_cnt == p_cnt:
res.append(0)
for i in range(m,n):
# 维持窗口长度为m
# i-m位置的字母被弹出,该字母的位置计数减1
s_cnt[ord(s[i-m]) - ord('a')] -= 1
# i位置的字母新加入,该字母的位置计数加1
s_cnt[ord(s[i]) - ord('a')] += 1
if s_cnt == p_cnt:
res.append(i-m+1)
return res
560. 和为k的子数组
# https://www.bilibili.com/video/BV1d54y127ri/?spm_id_from=333.337.search-card.all.click&vd_source=e3e285b6e46a418066b3eff2f933d941
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
cur_sum = 0
adict = {}
adict[0] = 1
count = 0
for num in nums:
cur_sum += num
if cur_sum - k in adict:
count += adict[cur_sum - k]
# 每一个cur_sum 最终都必须在adict里
if cur_sum in adict:
adict[cur_sum] += 1
else:
adict[cur_sum] = 1
return count