1. 力扣hot100系列技巧题解析
作为一名刷过3000+题的算法老手,我发现在力扣hot100题库中,前20%的题目往往涵盖了80%的核心解题技巧。这个系列将拆解hot100中最具代表性的技巧题型,重点分享那些让解题效率翻倍的"思维快捷键"。
2. 高频技巧题型精讲
2.1 双指针的三种经典范式
双指针看似简单,实际有细微的模式差异。以第11题"盛最多水的容器"为例:
def maxArea(height): left, right = 0, len(height)-1 res = 0 while left < right: res = max(res, min(height[left], height[right])*(right-left)) if height[left] < height[right]: left += 1 else: right -= 1 return res这里的关键在于理解:
- 对向指针的移动逻辑(总是移动较矮的一边)
- 面积计算的数学本质(宽度×最小高度)
- 贪心选择的正确性证明(局部最优导致全局最优)
实战经验:遇到数组/链表类问题时,先考虑双指针是否适用。对向指针适合有序数组,同向指针适合维护滑动窗口。
2.2 动态规划的降维技巧
以第70题"爬楼梯"为例,标准解法是:
def climbStairs(n): if n <= 2: return n dp = [0]*(n+1) dp[1], dp[2] = 1, 2 for i in range(3, n+1): dp[i] = dp[i-1] + dp[i-2] return dp[n]但通过观察可以发现只需要前两个状态:
def climbStairs(n): if n <= 2: return n a, b = 1, 2 for _ in range(3, n+1): a, b = b, a+b return b这种空间优化在股票买卖类问题中尤其重要(如第121题)。
2.3 回溯算法的剪枝艺术
第46题"全排列"展示了经典回溯框架:
def permute(nums): res = [] def backtrack(path, used): if len(path) == len(nums): res.append(path.copy()) return for i in range(len(nums)): if not used[i]: used[i] = True path.append(nums[i]) backtrack(path, used) path.pop() used[i] = False backtrack([], [False]*len(nums)) return res优化点包括:
- 使用位掩码替代used数组(当nums长度<32时)
- 提前终止条件(如组合总和问题)
- 排序后的去重剪枝(如第47题)
3. 算法优化实战技巧
3.1 时间复杂度分析的三个维度
以第1题"两数之和"为例:
- 暴力法:O(n²)时间,O(1)空间
- 哈希表:O(n)时间,O(n)空间
- 双指针(需先排序):O(nlogn)时间,O(1)空间
重要心得:面试时先明确说明各种解法的时间/空间复杂度,再写代码。这比直接写最优解更能展示思维过程。
3.2 边界条件的防御性编程
常见陷阱包括:
- 数组为空或单元素(第53题最大子数组和)
- 整数溢出(第7题整数反转)
- 指针越界(第19题删除链表倒数第N个节点)
以第5题"最长回文子串"为例:
def longestPalindrome(s): def expand(l, r): while l >=0 and r < len(s) and s[l] == s[r]: l -= 1 r += 1 return s[l+1:r] res = "" for i in range(len(s)): res = max(res, expand(i,i), expand(i,i+1), key=len) return res注意expand函数中返回的是s[l+1:r]而非s[l:r],这是为了避免边界溢出。
4. 高频问题分类速查
4.1 字符串处理技巧
| 题目 | 技巧 | 时间复杂度 |
|---|---|---|
| 第3题 无重复字符的最长子串 | 滑动窗口+哈希 | O(n) |
| 第20题 有效的括号 | 栈匹配 | O(n) |
| 第49题 字母异位词分组 | 哈希+排序 | O(nklogk) |
4.2 树形结构解题模板
前序遍历(第94题):
def inorderTraversal(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层次遍历(第102题):
def levelOrder(root): if not root: return [] res = [] q = deque([root]) while q: level = [] for _ in range(len(q)): node = q.popleft() level.append(node.val) if node.left: q.append(node.left) if node.right: q.append(node.right) res.append(level) return res4.3 图论问题速解方法
- 拓扑排序(第207题课程表)
- 并查集(第200题岛屿数量)
- Dijkstra算法(第743题网络延迟时间)
5. 刷题进阶路线建议
- 第一阶段:按hot100顺序刷,每题限时30分钟
- 第二阶段:按题型分类重刷,总结模板
- 第三阶段:模拟面试环境,白板编程
- 终极目标:能向他人清晰讲解每题的多种解法
我个人的刷题本上记录着每个错题的三个关键点:
- 当时卡壳的原因
- 最优解的核心思路
- 同类问题的识别特征
这种分类总结的方法让我在最近6场面试中算法题全部一次AC。记住:刷题质量远比数量重要,吃透20道经典题胜过模糊刷200题。