1. 题目背景与解题思路
2026年2月11日这组OJ题目编号69-71,从编号规律来看应该属于某个在线判题系统的中级难度题目。这类题目通常考察数据结构与算法的综合应用能力,特别是针对特定问题的优化解法。
根据我的刷题经验,这类连续编号的题目往往存在某种内在联系。可能是:
- 同一类问题的不同变种(如二叉树遍历的三种方式)
- 难度递进的相关问题(如从暴力解法到动态规划优化)
- 使用相同数据结构的多个应用场景
2. 题目69:矩阵中的最长递增路径
2.1 问题描述
(典型描述示例)给定一个m×n的整数矩阵,找出最长严格递增路径的长度。对于每个单元格,你可以向上下左右四个方向移动。
示例: 输入:matrix = [ [9,9,4], [6,6,8], [2,1,1] ] 输出:4 (最长路径是1→2→6→9)
2.2 解题思路
这类矩阵搜索问题通常有几种经典解法:
- DFS+记忆化:时间复杂度O(mn)
def longestIncreasingPath(matrix): if not matrix: return 0 m, n = len(matrix), len(matrix[0]) memo = [[0]*n for _ in range(m)] def dfs(i,j): if memo[i][j]: return memo[i][j] for x,y in [(i+1,j),(i-1,j),(i,j+1),(i,j-1)]: if 0<=x<m and 0<=y<n and matrix[x][y]>matrix[i][j]: memo[i][j] = max(memo[i][j], dfs(x,y)) memo[i][j] += 1 return memo[i][j] return max(dfs(i,j) for i in range(m) for j in range(n))- 拓扑排序:将矩阵视为有向图,统计入度后分层剥离
2.3 优化技巧
- 记忆化存储时可以用原矩阵作为visited标记
- 方向数组用dx=[1,-1,0,0], dy=[0,0,1,-1]更高效
- Python中可以functools.lru_cache实现自动记忆化
3. 题目70:课程安排III
3.1 问题描述
有n门课程,课程i需要在duration[i]天内完成,并且必须在lastDay[i]之前完成。求最多可以安排多少门课程。
示例: 输入:courses = [[100,200],[200,1300],[1000,1250],[2000,3200]] 输出:3
3.2 贪心算法实现
这类调度问题通常需要按某种规则排序后贪心处理:
import heapq def scheduleCourse(courses): courses.sort(key=lambda x: x[1]) heap = [] time = 0 for dur, end in courses: if time + dur <= end: heapq.heappush(heap, -dur) time += dur elif heap and -heap[0] > dur: time += dur + heapq.heappop(heap) heapq.heappush(heap, -dur) return len(heap)3.3 关键点分析
- 按截止时间排序是贪心选择的基础
- 使用最大堆(通过存储负数实现)维护当前已选课程
- 当遇到冲突时,替换掉持续时间最长的课程
4. 题目71:编辑距离
4.1 经典动态规划问题
给定两个单词word1和word2,计算将word1转换成word2所需的最少操作数。允许的操作:
- 插入一个字符
- 删除一个字符
- 替换一个字符
4.2 DP表格解法
def minDistance(word1, word2): m, n = len(word1), len(word2) dp = [[0]*(n+1) for _ in range(m+1)] for i in range(m+1): dp[i][0] = i for j in range(n+1): dp[0][j] = j for i in range(1, m+1): for j in range(1, n+1): if word1[i-1] == word2[j-1]: dp[i][j] = dp[i-1][j-1] else: dp[i][j] = 1 + min( dp[i-1][j], # 删除 dp[i][j-1], # 插入 dp[i-1][j-1] # 替换 ) return dp[m][n]4.3 空间优化
可以优化到O(n)空间,只保留前一行和当前行的状态:
def minDistance(word1, word2): m, n = len(word1), len(word2) prev = [j for j in range(n+1)] for i in range(1, m+1): curr = [i]*(n+1) for j in range(1, n+1): if word1[i-1] == word2[j-1]: curr[j] = prev[j-1] else: curr[j] = 1 + min( prev[j], # 删除 curr[j-1], # 插入 prev[j-1] # 替换 ) prev = curr return prev[n]5. 刷题经验分享
5.1 调试技巧
- 对于DP问题,先打印出完整的DP表格验证状态转移
- 使用小规模测试用例(如空输入、单元素)检查边界条件
- 在OJ平台超时时,本地用大随机数据测试
5.2 复杂度分析要点
- 矩阵问题要考虑行列双重循环
- 带排序的解法要加上排序的复杂度
- 递归解法要明确递归深度和每层复杂度
5.3 代码模板整理
建议将以下模板保存为代码片段:
- 方向数组:dirs = [(1,0),(-1,0),(0,1),(0,-1)]
- 堆的使用:import heapq;heapq.heappush/pop
- DP表格初始化:dp = [[0]*n for _ in range(m)]
6. 同类题目推荐
如果想继续巩固这些题型,可以尝试:
- 矩阵类:329(本题原型)、200岛屿数量
- 贪心调度:630课程表III、1353最多可以参加的会议数目
- 编辑距离:72(本题)、161相隔一个字符
刷题时注意总结题型特征,比如看到"最长/最短"、"最少操作"等关键词,就能快速联想到相应解法。这三道题虽然表面不同,但都体现了算法竞赛中的核心思维:如何将问题转化为经典模型,以及如何优化基础解法。