算法刷题笔记:动态规划与优先队列实战解析

发布时间:2026/11/5 2:58:00
算法刷题笔记:动态规划与优先队列实战解析

1. 刷题笔记的价值与意义

作为一名程序员,我坚持刷算法题已经三年多了。2026年1月22日这天的刷题笔记特别值得记录,因为这天遇到的几道题目涵盖了多个经典算法模式。刷题不仅仅是应付面试的手段,更是锻炼编程思维的有效方式。

算法题就像健身房的器械训练,每道题都在针对性地锻炼特定的"思维肌肉"。通过系统性地记录和整理刷题笔记,可以清晰地看到自己的进步轨迹,也能在遇到类似问题时快速回顾解题思路。

2. 当日刷题题目概览

2.1 题目选择策略

我通常会按照"1简单+2中等+1困难"的比例来选择每日刷题组合。2026.1.22这天选择的题目是:

  1. 简单题:两数之和(经典热身题)
  2. 中等题:二叉树的中序遍历(递归与迭代实现)
  3. 中等题:最长回文子串(动态规划解法)
  4. 困难题:合并K个升序链表(优先队列应用)

提示:建议每次刷题都包含不同难度,这样既能保持信心,又能持续挑战自己。

2.2 刷题环境配置

我的刷题环境配置如下:

  • IDE:VS Code + LeetCode插件
  • 语言:Python 3.9(兼顾简洁与效率)
  • 辅助工具:本地测试用例生成脚本
  • 笔记工具:Markdown格式记录,同步到GitHub
# 本地测试用例示例 def test_two_sum(): nums = [2,7,11,15] target = 9 assert two_sum(nums, target) == [0,1]

3. 题目详解与解题思路

3.1 两数之和的多种解法

这道经典题目看似简单,但蕴含着多种解题思路:

  1. 暴力枚举法:双重循环,时间复杂度O(n²)
  2. 哈希表法:空间换时间,时间复杂度O(n)
  3. 排序+双指针法:需要额外空间存储索引
def two_sum(nums, target): hashmap = {} for i, num in enumerate(nums): complement = target - num if complement in hashmap: return [hashmap[complement], i] hashmap[num] = i return []

注意:哈希表解法要注意处理重复元素的情况,测试用例要考虑边界条件。

3.2 二叉树中序遍历的迭代实现

递归解法虽然简洁,但理解迭代解法对掌握栈的应用很有帮助:

def inorder_traversal(root): res = [] stack = [] curr = root while curr or stack: while curr: stack.append(curr) curr = curr.left curr = stack.pop() res.append(curr.val) curr = curr.right return res

关键点:

  • 使用栈模拟递归调用
  • 先一路向左到底
  • 处理节点后再转向右子树

3.3 最长回文子串的动态规划解法

这道题展示了动态规划的典型应用:

  1. 定义dp[i][j]表示s[i...j]是否为回文
  2. 状态转移方程:
    • 基本情况:单个字符是回文
    • 两个相同字符是回文
    • 更长串:首尾相同且中间是回文
def longest_palindrome(s): n = len(s) dp = [[False]*n for _ in range(n)] res = "" for l in range(n): for i in range(n-l): j = i + l if l == 0: dp[i][j] = True elif l == 1: dp[i][j] = (s[i] == s[j]) else: dp[i][j] = (s[i] == s[j] and dp[i+1][j-1]) if dp[i][j] and l+1 > len(res): res = s[i:j+1] return res

3.4 合并K个升序链表的优先队列解法

这道困难题展示了优先队列(堆)的典型应用场景:

import heapq def merge_k_lists(lists): dummy = ListNode(0) curr = dummy heap = [] for i in range(len(lists)): if lists[i]: heapq.heappush(heap, (lists[i].val, i)) lists[i] = lists[i].next while heap: val, i = heapq.heappop(heap) curr.next = ListNode(val) curr = curr.next if lists[i]: heapq.heappush(heap, (lists[i].val, i)) lists[i] = lists[i].next return dummy.next

优化点:

  • 使用元组存储值和链表索引
  • 每次只push一个节点,保持堆的大小为O(k)
  • 时间复杂度O(Nlogk),N是总节点数

4. 刷题技巧与经验分享

4.1 高效刷题的方法论

  1. 分类刷题法:按算法类型集中练习(如一周专攻动态规划)
  2. 五步解题法:
    • 理解题意
    • 列举可能的解法
    • 选择最优解法
    • 编写代码
    • 测试与优化
  3. 错题本机制:记录错误原因和正确思路

4.2 常见错误与调试技巧

典型错误案例:

  1. 边界条件处理不当(空输入、单个元素等)
  2. 循环终止条件错误
  3. 指针/索引越界
  4. 特殊数据结构使用不当

调试技巧:

  • 使用print语句输出中间变量
  • 绘制数据结构变化图
  • 编写测试用例覆盖边界条件
  • 使用调试器逐步执行

4.3 刷题的时间管理

我个人的时间分配建议:

  • 15分钟:理解题目和思考解法
  • 20分钟:实现第一种解法
  • 15分钟:优化和测试
  • 10分钟:记录笔记和总结

如果超过这个时间还没思路,建议查看题解,但一定要自己重新实现一遍。

5. 刷题笔记的整理方法

5.1 笔记内容结构

每道题的笔记应包含:

  1. 题目描述(用自己的话复述)
  2. 解题思路(多种解法比较)
  3. 代码实现(带注释)
  4. 复杂度分析
  5. 相关题目链接

5.2 知识图谱构建

我使用思维导图工具将算法知识点连接起来,例如:

  • 动态规划 → 背包问题 → 子集和问题
  • 树 → 遍历方式 → 递归/迭代实现
  • 图 → DFS/BFS → 拓扑排序

5.3 定期回顾机制

我设置了以下回顾周期:

  • 次日:快速浏览前一天笔记
  • 周末:总结本周刷题情况
  • 月末:整理高频考点和薄弱环节

6. 从刷题到面试的转化

6.1 面试中的表达技巧

在面试中讲解算法题时要注意:

  1. 先明确问题边界和假设
  2. 讨论时间和空间复杂度权衡
  3. 考虑可能的优化方向
  4. 处理面试官的follow-up问题

6.2 实际工程中的算法应用

刷题中学到的算法在实际工作中的典型应用:

  • 哈希表:缓存实现、去重
  • 优先队列:任务调度
  • 图算法:社交网络分析
  • 字符串算法:搜索引擎

6.3 持续学习的资源推荐

我常使用的进阶资源:

  1. 《算法导论》(经典教材)
  2. LeetCode讨论区(优质题解)
  3. 算法可视化网站(直观理解)
  4. 技术博客(实战经验分享)

刷题三年多来,最大的体会是:算法能力的提升不是线性的,而是阶梯式的。每次突破一个瓶颈期,解决问题的能力就会上一个新台阶。2026.1.22这天的刷题笔记,记录了我在动态规划和优先队列应用上的新理解,也为后续的算法学习打下了更坚实的基础。