977. 有序数组的平方
暴力:平方每个元素,然后排序,时间复杂度取决于排序算法。
思路:有效利用题干中的“非递减数组”,意味着较大值在数组右端,有以下两个观察:
1. 若不含负数,平方后数组的较大值依然在右端。
2. 若包含负数,平方后数组的较大值在左端或右端,呈山谷状。
由于平方后较大值一定在两端,因此使用双指针从两端向中间遍历,每次取较大值插入新开辟的数组。
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
left, right = 0, len(nums) - 1
result = [float('inf')] * len(nums)
index = len(nums) - 1
# 为什么不是 left < right ?
# 设想还剩最后两个元素 a,b
# 对比后将 a。赋值给 result
# 此时 left 移动,与 right 重合,跳出循环,b 即被遗漏
while left <= right:
if nums[left] ** 2 < nums[right] ** 2:
result[index] = nums[right] ** 2
right -= 1
# nums[left] == nums[right]的情况下,给result赋值任意一个都行,所以和其他两种情况合并
else:
result[index] = nums[left] ** 2
left += 1
index -= 1
return result
# 时间复杂度:
# O(n)
209. 长度最小的子数组
暴力:两层for循环遍历所有子数组,过程维护一个满足条件的最小长度,O(n²)。
思路:实际上,当找到一个符合条件的子数组, 不需要再去判断任何更长的子数组。
我们使用双指针来维护一个滑动窗口,左右指针指向第一个元素,右指针先行,直到找到一个满足条件的窗口,此时只需要寻找更短的窗口,通过移动左指针缩小窗口,维护一个 min_len。当窗口缩小到不满足条件的时候,再次移动右指针,也就是重复此过程。
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
cur_sum = 0
left, right = 0, 0
min_len = float('inf')
while right < len(nums):
cur_sum += nums[right]
# 当找到符合条件的窗口,不断移动左指针来缩小窗口,直至不符合条件
while cur_sum >= target:
min_len = min(min_len, right - left + 1)
cur_sum -= nums[left]
left += 1
right += 1
# 循环结束后,有可能不存在符合条件的子数组
# 此时 min_len 未被更新,保持 float('inf') 的初始化状态
# 根据题干,需返回 0
return min_len if min_len != float('inf') else 0
# 时间复杂度:
# 每个元素都会进出一次窗口
# O(2n) = O(n)
59. 螺旋矩阵II
模拟题,考察代码掌控能力,多练多记吧!
本题的关键是,起始点 startx、starty、边界 n - offset ,以及填充顺序的理解。
具体注释放在了代码相应位置,以供辅助理解。
模拟过程:
填充第一行:行不变(startx), 列变化(starty -> n - offset)
填充第三列:列不变(n - offset),行变化(startx -> n - offset)
填充第三行:行不变(n - offset),列变化(n - offset -> starty)
填充第一列:列不变(starty), 行变化(n - offset -> startx)
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
# 创建矩阵
matrix = [[0] * n for _ in range(n)]
startx, starty = 0, 0
# mid用来针对n为奇数时,矩阵存在一个中心点,需要手动更新
loop, mid = n // 2, n // 2
count = 1
for offset in range(1, loop + 1):
# 上行,左至右
# x 不动,保持在 startx
# 移动 y,从 starty 至 n - offset
for i in range(starty, n - offset):
matrix[startx][i] = count
count += 1
# 右列,上至下
# y 不动,保持在 n - offset
# x 移动,从 startx 至 n - offset
for i in range(startx, n - offset):
matrix[i][n - offset] = count
count += 1
# 下行,右至左
# x 不动,保持在 n - offset
# y 移动,从 n - offset 至 starty
for i in range(n - offset, starty, -1):
matrix[n - offset][i] = count
count += 1
# 左列,下至上
# y 不动,保持在 starty
# x 移动,从 n - offset 至 startx
for i in range(n - offset, startx, -1):
matrix[i][starty] = count
count += 1
# 一圈更新完成,朝内部offset一圈
startx += 1
starty += 1
# 如果n为基数,会存在一个单独的中心点,需要手动更新
if n % 2 != 0:
matrix[mid][mid] = count
return matrix
# 时间复杂度:
# 为n²个元素赋值一次
# O(n²)