1. 力扣刷题的价值与意义
作为一名程序员,我坚持力扣刷题已经三年多了。最初只是为了应付面试,后来发现这种刻意练习对编程能力的提升远超预期。每天解决1-2道算法题,就像给大脑做健身操,不仅保持思维敏捷,还能积累各种"解题套路"。
力扣(LeetCode)题库目前有2000+题目,覆盖数据结构、算法、数据库、Shell等方向。其中算法题按难度分为简单、中等和困难三个级别。我建议从"热题100"开始,这些题目出现频率高,解法经典,是打基础的好材料。
新手常见误区:盲目追求刷题数量。实际上,吃透一道中等题的多种解法,比快速AC十道简单题更有价值。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 日刷47题解析
2.1 题目背景与要求
第47题是经典的"全排列II",属于回溯算法的典型应用。题目给定一个可包含重复数字的序列,要求返回所有不重复的全排列。例如:
code复制输入:[1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
与第46题(无重复数字的全排列)相比,本题的难点在于如何避免生成重复的排列组合。这也是面试中经常被追问的考察点。
2.2 解题思路分析
2.2.1 回溯算法框架
回溯算法的通用模板如下:
python复制def backtrack(路径, 选择列表):
if 满足结束条件:
结果.append(路径)
return
for 选择 in 选择列表:
做选择
backtrack(路径, 选择列表)
撤销选择
对于本题,我们需要:
- 先对数组排序,让相同数字相邻
- 在遍历选择时,跳过与前一个相同且未被使用的数字
2.2.2 关键代码实现
Python解法示例:
python复制class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
nums.sort() # 关键步骤:排序
res = []
used = [False] * len(nums)
def backtrack(path):
if len(path) == len(nums):
res.append(path.copy())
return
for i in range(len(nums)):
if used[i]: continue
# 剪枝条件:当前数字与前一个相同,且前一个未被使用
if i > 0 and nums[i] == nums[i-1] and not used[i-1]:
continue
used[i] = True
path.append(nums[i])
backtrack(path)
path.pop()
used[i] = False
backtrack([])
return res
时间复杂度分析:最坏情况下O(n×n!),但通过剪枝优化后实际运行会快很多。
2.3 调试与优化技巧
- 可视化调试:在递归调用前后打印路径和选择列表,观察程序执行流程
- 剪枝优化:使用
used数组记录已使用的元素,避免重复选择 - 去重技巧:排序后通过
nums[i] == nums[i-1]判断重复元素
实际编码时容易犯的错误:忘记在回溯后恢复
used数组状态,导致后续选择出错。
3. 同类题型拓展
3.1 排列组合问题家族
力扣上常见的排列组合问题包括:
- 无重复全排列(46题)
- 有重复全排列(47题)
- 组合总和(39、40题)
- 子集问题(78、90题)
这些问题都可以用回溯算法解决,区别主要在于剪枝条件和终止条件。
3.2 其他解法对比
除了回溯法,这类问题还可以:
- 使用
itertools.permutations(Python内置库) - 递归交换元素位置
- 使用字典序生成法
但面试时通常要求手写回溯实现,以考察对算法本质的理解。
4. 刷题方法论
4.1 五步刷题法
我总结的高效刷题流程:
- 独立思考15分钟,尝试各种解法
- 写出初版代码并提交
- 查看错误用例,针对性调试
- 学习最优解,比较差异
- 隔天重写,确保真正掌握
4.2 题目分类策略
建议按算法类型分类刷题:
- 数组:双指针、滑动窗口
- 链表:虚拟头节点、快慢指针
- 树:DFS/BFS、递归
- 动态规划:背包问题、字符串匹配
- 图:拓扑排序、最短路径
每周专注一个类别,建立系统性的知识框架。
5. 实战经验分享
5.1 调试技巧
遇到递归问题时:
- 画出递归树,标注每层状态
- 使用缩进打印调试信息
python复制def backtrack(path, depth=0):
print(" "*depth + f"Enter: {path}")
# ...
print(" "*depth + f"Exit: {path}")
5.2 性能优化
当提交超时时:
- 检查是否有重复计算(可用记忆化优化)
- 分析剪枝条件是否充分
- 考虑更优算法(如DP替代回溯)
5.3 面试应用
在面试中讲解回溯题时:
- 先说明问题复杂度(解空间大小)
- 解释剪枝策略的数学依据
- 讨论时间/空间复杂度
我通常会用白板画出递归树,标注剪枝位置,这样能给面试官留下深刻印象。
6. 学习资源推荐
- 《算法导论》回溯算法章节
- 力扣官方题解视频
- labuladong的算法小抄
- 代码随想录网站
建议准备一个错题本,记录每道题的:
- 初始思路
- 错误原因
- 最优解法
- 同类题目
坚持三个月后,你会发现遇到新题时能快速联想到相似解法。我现在保持每天至少一道中等题的节奏,周末总结当周的所有解法。这种持续的精进,让我的代码能力有了质的飞跃。
