1. 链表与基础算法复习指南
作为一名刷过上千道LeetCode题的老手,我深知算法复习需要系统性和针对性。今天这份笔记记录了我第32天的复习内容,重点覆盖了链表操作、滑动窗口、前缀和等高频考点。这些题目在面试中出现概率极高,掌握它们能让你在技术面试中游刃有余。
2. 核心算法题型精讲
2.1 前缀和与子串问题
前缀和(Prefix Sum)是处理子数组/子串问题的利器。其核心思想是通过预处理构建一个前缀和数组,使得任意区间的和可以在O(1)时间内计算得出。
以经典题"和为K的子数组"为例:
python复制def subarraySum(nums, k):
prefix_sum = {0: 1}
current_sum = 0
count = 0
for num in nums:
current_sum += num
count += prefix_sum.get(current_sum - k, 0)
prefix_sum[current_sum] = prefix_sum.get(current_sum, 0) + 1
return count
关键点:利用哈希表存储前缀和出现次数,通过current_sum - k查找符合条件的子数组
2.2 滑动窗口技巧
滑动窗口是处理子串/子数组问题的另一大利器,特别适合"满足某种条件的最短/最长子串"类问题。
"最小覆盖子串"的标准解法:
python复制def minWindow(s, t):
from collections import defaultdict
target = defaultdict(int)
for c in t:
target[c] += 1
left = 0
min_len = float('inf')
counter = len(t)
result = ""
for right, c in enumerate(s):
if target[c] > 0:
counter -= 1
target[c] -= 1
while counter == 0:
if right - left + 1 < min_len:
min_len = right - left + 1
result = s[left:right+1]
if target[s[left]] == 0:
counter += 1
target[s[left]] += 1
left += 1
return result
注意事项:维护一个counter变量表示还需要匹配的字符数,当counter=0时开始收缩左边界
3. 链表专题深度解析
3.1 基础链表操作
链表问题虽然形式多样,但核心操作不外乎以下几种:
- 遍历
- 节点插入/删除
- 反转
- 合并
"合并两个有序链表"的标准写法:
python复制def mergeTwoLists(l1, l2):
dummy = ListNode(0)
current = dummy
while l1 and l2:
if l1.val < l2.val:
current.next = l1
l1 = l1.next
else:
current.next = l2
l2 = l2.next
current = current.next
current.next = l1 if l1 else l2
return dummy.next
3.2 进阶链表问题
"K个一组反转链表"是面试中的高频难题,需要熟练掌握:
python复制def reverseKGroup(head, k):
def reverse(head, tail):
prev = tail.next
curr = head
while prev != tail:
next_node = curr.next
curr.next = prev
prev = curr
curr = next_node
return tail, head
dummy = ListNode(0)
dummy.next = head
pre = dummy
while head:
tail = pre
for _ in range(k):
tail = tail.next
if not tail:
return dummy.next
next_group = tail.next
head, tail = reverse(head, tail)
pre.next = head
tail.next = next_group
pre = tail
head = tail.next
return dummy.next
实操技巧:使用dummy节点简化头节点处理,reverse函数返回新的头和尾
4. 高频算法题型解题模板
4.1 双指针技巧
双指针是解决数组/链表问题的通用技巧,常见模式包括:
- 快慢指针(环形链表检测)
- 左右指针(两数之和)
- 滑动窗口(最小覆盖子串)
"环形链表II"的标准解法:
python复制def detectCycle(head):
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
break
else:
return None
while head != slow:
head = head.next
slow = slow.next
return head
4.2 回溯与动态规划
"最大子数组和"的几种解法对比:
- 暴力解法:O(n^2)
- 分治法:O(nlogn)
- Kadane算法(最优):O(n)
Kadane算法实现:
python复制def maxSubArray(nums):
max_current = max_global = nums[0]
for num in nums[1:]:
max_current = max(num, max_current + num)
max_global = max(max_global, max_current)
return max_global
5. 解题经验与避坑指南
5.1 常见错误分析
- 链表问题:
- 忘记处理头节点/尾节点
- 指针操作顺序错误导致链表断裂
- 循环链表检测时忘记检查fast.next是否为None
- 滑动窗口问题:
- 窗口收缩条件判断错误
- 忘记更新结果位置
- 哈希表计数处理不当
5.2 调试技巧
- 对于链表问题:
- 先画出链表结构图
- 标注每个指针的位置
- 逐步模拟指针移动过程
- 对于递归问题:
- 明确递归终止条件
- 记录递归深度
- 使用print语句输出关键变量
5.3 时间管理建议
根据我的刷题经验,建议时间分配:
- 简单题:5分钟内完成
- 中等题:15-20分钟
- 难题:30分钟尝试后看题解
对于"旋转图像"这类矩阵问题,可以记住这个通用解法:
python复制def rotate(matrix):
n = len(matrix)
# 先转置矩阵
for i in range(n):
for j in range(i, n):
matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
# 再翻转每一行
for i in range(n):
matrix[i] = matrix[i][::-1]
6. 刷题策略与复习计划
6.1 分类刷题法
建议按题型分类刷题,比如:
- 第一周:链表专题
- 第二周:二叉树专题
- 第三周:动态规划专题
- 第四周:图论专题
每个专题至少完成20道经典题目,包括:
- 5道简单题(巩固基础)
- 10道中等题(重点突破)
- 5道难题(挑战自我)
6.2 错题本管理
建立错题本记录:
- 题目基本信息(题号、名称、难度)
- 第一次解题思路
- 错误原因分析
- 正确解法
- 同类题目链接
对于"缺失的第一个正数"这类hard题目,我的错题记录如下:
python复制def firstMissingPositive(nums):
n = len(nums)
# 第一次尝试:使用哈希表,但空间复杂度不符合要求
# 正确解法:原地哈希
for i in range(n):
while 1 <= nums[i] <= n and nums[nums[i]-1] != nums[i]:
nums[nums[i]-1], nums[i] = nums[i], nums[nums[i]-1]
for i in range(n):
if nums[i] != i+1:
return i+1
return n+1
6.3 模拟面试训练
建议每周进行2-3次模拟面试:
- 使用LeetCode的模拟面试功能
- 设置45分钟计时
- 随机选择3-5道题目
- 完成后复盘解题过程
对于"螺旋矩阵"这类题目,在面试中建议:
- 明确边界条件
- 先写出伪代码
- 逐步实现每个步骤
- 测试边界用例
python复制def spiralOrder(matrix):
if not matrix:
return []
rows, cols = len(matrix), len(matrix[0])
top, bottom = 0, rows-1
left, right = 0, cols-1
res = []
while top <= bottom and left <= right:
# 从左到右
for i in range(left, right+1):
res.append(matrix[top][i])
top += 1
# 从上到下
for i in range(top, bottom+1):
res.append(matrix[i][right])
right -= 1
if top <= bottom:
# 从右到左
for i in range(right, left-1, -1):
res.append(matrix[bottom][i])
bottom -= 1
if left <= right:
# 从下到上
for i in range(bottom, top-1, -1):
res.append(matrix[i][left])
left += 1
return res
在实际刷题过程中,我发现反复练习同一类型的题目确实能显著提高解题速度。比如链表反转这类基础操作,经过几十次练习后,现在基本能在1分钟内写出无bug的代码。对于准备面试的同学,我的建议是先把高频经典题目刷熟,再逐步扩展到其他题型。