1. 算法训练营第二天实战解析
今天继续算法训练营的实战练习,重点攻克两道经典题目:209.长度最小的子数组和59.螺旋矩阵II。这两道题分别代表了滑动窗口和模拟操作两大高频考点,在面试中出现概率极高。我把自己在AC过程中的思考路径、踩坑经验和优化技巧完整记录下来,希望能帮助到正在刷题的你。
2. 209.长度最小的子数组详解
2.1 题目核心分析
给定一个含有n个正整数的数组和一个正整数target,找出该数组中满足其和≥target的长度最小的连续子数组。如果不存在符合条件的子数组,返回0。
关键点在于:
- 数组元素都是正整数(这个条件决定了滑动窗口的可行性)
- 要求连续子数组
- 需要找到满足条件的最小长度
2.2 滑动窗口解法实现
滑动窗口是解决这类连续子数组问题的利器。具体实现步骤如下:
def minSubArrayLen(target, nums): left = 0 current_sum = 0 min_length = float('inf') for right in range(len(nums)): current_sum += nums[right] while current_sum >= target: min_length = min(min_length, right - left + 1) current_sum -= nums[left] left += 1 return min_length if min_length != float('inf') else 0重要提示:内层while循环是关键,不能写成if判断。因为收缩左边界可能需要多次操作才能使窗口和小于target。
2.3 复杂度分析与优化
时间复杂度:O(n),虽然看起来有嵌套循环,但每个元素最多被访问两次(加入窗口和移出窗口) 空间复杂度:O(1),只使用了常数个额外空间
实际测试中发现,当数组元素值较大时,可以加入提前终止的判断:
if nums[right] >= target: # 单个元素就满足条件 return 13. 59.螺旋矩阵II深度剖析
3.1 题目理解与建模
给定正整数n,生成一个包含1到n²所有元素,且元素按顺时针顺序螺旋排列的n×n正方形矩阵。
这道题考察的是对二维数组的精确控制和边界处理能力。关键在于:
- 确定填充的层数(n//2层)
- 明确每一圈填充的四个方向及其边界条件
- 处理n为奇数时中心点的特殊情况
3.2 分层模拟解法
最直观的解法是模拟螺旋填充过程:
def generateMatrix(n): matrix = [[0]*n for _ in range(n)] left, right = 0, n-1 top, bottom = 0, n-1 num = 1 while left <= right and top <= bottom: # 从左到右填充上边 for i in range(left, right+1): matrix[top][i] = num num += 1 top += 1 # 从上到下填充右边 for i in range(top, bottom+1): matrix[i][right] = num num += 1 right -= 1 # 从右到左填充下边 for i in range(right, left-1, -1): matrix[bottom][i] = num num += 1 bottom -= 1 # 从下到上填充左边 for i in range(bottom, top-1, -1): matrix[i][left] = num num += 1 left += 1 return matrix3.3 边界处理的常见陷阱
在实际编码中,最容易出错的是:
- 循环终止条件不完整(缺少对top<=bottom的判断)
- 第三步从右到左填充时,忘记检查if left <= right
- n为奇数时中心点的处理(上述代码已自动包含)
建议在纸上画出n=3和n=4的情况,一步步跟踪代码执行过程。
4. 两道题目的共通技巧
4.1 循环不变量原则
这两道题都体现了循环不变量思想:
- 滑动窗口中维护的是始终满足sum≥target的最小窗口
- 螺旋矩阵中每一圈填充后边界都会向内收缩
4.2 调试技巧分享
对于这类问题,可视化调试特别有效:
- 滑动窗口:打印出每一步的窗口左右边界和当前和
- 螺旋矩阵:在每步填充后打印出当前矩阵状态
例如调试螺旋矩阵时可以添加:
print(f"Step {num}:") for row in matrix: print(row) print()5. 同类问题扩展练习
为了巩固这两个解题技巧,推荐练习:
滑动窗口系列:
- 904.水果成篮
- 76.最小覆盖子串
- 3.无重复字符的最长子串
矩阵模拟系列:
- 54.螺旋矩阵
- 48.旋转图像
- 73.矩阵置零
6. 个人刷题心得
经过这两道题的训练,我总结了几个关键点:
滑动窗口问题要先明确三点:
- 窗口内是什么?
- 如何移动窗口起始位置?
- 如何移动窗口结束位置?
矩阵模拟问题要:
- 先确定处理几层/几圈
- 统一每边的处理规则(左闭右开或左闭右闭)
- 处理好最后可能剩下的中心点
在纸上画出小规模测试用例的执行过程,比直接敲代码更高效。
最后分享一个效率技巧:对于螺旋矩阵这类问题,可以预先定义方向数组,统一处理四个方向的移动,代码会更简洁但可能稍难理解。建议先掌握基础写法再尝试优化。