文章链接:
209.长度最小的子数组 代码随想录
59. 螺旋矩阵
视频链接:拿下滑动窗口! | LeetCode 209 长度最小的子数组_哔哩哔哩_bilibili
209. 长度最小的子数组
状态:二刷,7分钟AC,但while loop还是没有掌握牢固
思路:滑动窗口,关键在于确定滑动窗口的大小(即起止位置)
窗口起始位置的移动:当前窗口的值(子数组所有元素的和)大于等于s时,就要将起始指针向右移动了,即缩小滑动窗口,i += 1
窗口结束位置的移动:遍历数组的指针,for循环的索引
总结:
1. 第一次写时,用的是if sums >= target判断,而不是while loop。没有考虑清楚题目要求的‘最小数组’,要不断变更起始位置,不断判断子数组是否符合条件
2. DAY1的训练没有关注算法复杂度,之后需要重视起来
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
i, sums = 0, 0
result = float('inf')
for j in range(len(nums)):
sums += nums[j]
while sums >= target:
result = min(result, j-i+1)
sums -= nums[i]
i += 1
return result if result != float('inf') else 0
时间复杂度:O(n)
空间复杂度:O(1)
59. 螺旋矩阵
状态:二刷,23分钟AC,但其中debug了一次,对后两个for循环边界定义有误
思路:类似二分法的循环不变原则,保持【左闭右开)原则来处理每条边,另外注意引入变量startx, starty, offset
总结:
1. 题目本身难度不大,但是一定要保持【左闭右开)原则,同时注意每个for循环的取值边界 (自己画一个矩阵来模拟过程更易于理解)
2. 确定好loops的个数,注意是否需要处理中心点(中心点的索引也可以提前定义好为mid=n//2)
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
matrix = [[0] * n for _ in range(n)]
startx, starty = 0, 0
offset = 1
count = 1
loops = n // 2
for loop in range(loops):
for j in range(starty, n-offset):
matrix[startx][j] = count
count += 1
for i in range(startx, n-offset):
matrix[i][n-offset] = count
count += 1
# range(n-offset, starty, -1) 而不是range(n-offset, 0, -1)
# 后者只考虑了matrix最外围的情况,下同
for j in range(n-offset, starty, -1):
matrix[n-offset][j] = count
count += 1
for i in range(n-offset, startx, -1):
matrix[i][starty] = count
count += 1
startx += 1
starty += 1
offset += 1
if n%2 != 0:
matrix[startx][starty] = count
return matrix
时间复杂度:O(n^2)
空间复杂度:O(1)
附加训练:
总结:
1. 一刷,直接看随想录的思路,学习“前缀和”思想:注意计算区间和时的索引取值范围。例如,计算数组list[a]到list[b]的区间和时,对应的前缀和减法运算是p[b] - p[a-1]。
2. 熟悉ACM模式,注意python中读取输入数据的方式之一为:
input = sys.stdin.read() # input为字符串
data = input.split() # split()将input字符串切片,转化为一维数组data,每个元素还是字符串型
n = int(data[idx]) # 要将字符串转换为int整型
总结:
1. 直接看随想录的思路,结合前缀和思想,再次训练ACM模式
2. 重述代码思路:
1)按行依次读取n*m个数据,构建矩阵,同时计算总和sums
2)利用前缀和思想,分别计算矩阵行总和及列总和,方便下一步计算差值
3)模拟区块划分:分别按照行、列进行划分,计算子区域差值。