1. 为什么需要LeetCode热题100的Python3题解?
LeetCode作为程序员面试的"金标准",其题目质量和考察范围直接影响着求职者的准备策略。热题100榜单是平台根据企业实际面试高频出现题目统计得出,具有极强的实战指导意义。而Python3凭借简洁的语法和丰富的数据结构支持,已成为算法面试的首选语言之一。
在普通数组和矩阵这两类题型中,初学者常陷入几个典型困境:
- 对Python内置的列表(list)和NumPy数组混为一谈,导致方法调用错误
- 矩阵遍历时过度依赖显式循环,忽略Python特有的切片和迭代机制
- 解题时思路正确但被语法细节卡住,比如浅拷贝导致的矩阵修改异常
我精选的这组题解会特别注重:
- 每个解法都附带执行效率分析(时间/空间复杂度)
- 关键步骤给出替代写法对比
- 针对Python3的特性优化传统解法
- 标注面试官可能追问的变形题目
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 普通数组类高频题型精讲
2.1 最大子数组和(LeetCode 53)
这是动态规划的经典入门题,Python3的实现可以精简到令人发指:
python复制def maxSubArray(nums):
current = max_sum = nums[0]
for num in nums[1:]:
current = max(num, current + num)
max_sum = max(max_sum, current)
return max_sum
关键技巧:current维护的是"以当前元素结尾的最大和",这个定义让状态转移变得直观。面试时可能会要求返回子数组本身而非只是和,这时候需要额外维护起止索引。
时间复杂度O(n)的证明:
- 单次遍历数组(n-1次比较)
- 每次迭代执行两次max操作(O(1))
- 总操作次数为3(n-1),仍为线性阶
2.2 合并区间(LeetCode 56)
这道题考察的是对自定义排序的理解,Python3的解法充分展示了lambda表达式的威力:
python复制def merge(intervals):
intervals.sort(key=lambda x: x[0])
merged = []
for interval in intervals:
if not merged or merged[-1][1] < interval[0]:
merged.append(interval)
else:
merged[-1][1] = max(merged[-1][1], interval[1])
return merged
实际编码时容易踩的坑:
- 直接修改原区间列表可能导致意外行为
- 忘记处理空输入的情况(面试官常设的边界条件)
- 区间比较时错误使用<=而不是<
2.3 旋转数组(LeetCode 189)
三种经典解法对比:
| 方法 | 时间复杂度 | 空间复杂度 | 适用场景 |
|---|---|---|---|
| 暴力旋转 | O(n*k) | O(1) | 不推荐,仅作理解用 |
| 额外数组 | O(n) | O(n) | 内存充足时最清晰 |
| 三次反转 | O(n) | O(1) | 面试最优解 |
三次反转法的Python实现:
python复制def rotate(nums, k):
k %= len(nums)
nums.reverse()
nums[:k] = reversed(nums[:k])
nums[k:] = reversed(nums[k:])
注意点:k可能大于数组长度,需要先取模。切片操作创建的是新对象,要区分nums[:k].reverse()(无效)和nums[:k] = reversed(nums[:k])(有效)的区别。
3. 矩阵类高频题型详解
3.1 矩阵置零(LeetCode 73)
这道题的优化解法体现了空间复杂度的精妙控制:
python复制def setZeroes(matrix):
first_row_has_zero = any(matrix[0][j] == 0 for j in range(len(matrix[0])))
first_col_has_zero = any(matrix[i][0] == 0 for i in range(len(matrix)))
# 使用首行首列作为标记位
for i in range(1, len(matrix)):
for j in range(1, len(matrix[0])):
if matrix[i][j] == 0:
matrix[i][0] = 0
matrix[0][j] = 0
# 根据标记置零
for i in range(1, len(matrix)):
for j in range(1, len(matrix[0])):
if matrix[i][0] == 0 or matrix[0][j] == 0:
matrix[i][j] = 0
# 处理首行首列
if first_row_has_zero:
for j in range(len(matrix[0])):
matrix[0][j] = 0
if first_col_has_zero:
for i in range(len(matrix)):
matrix[i][0] = 0
空间优化原理:
- 传统方法需要O(m+n)空间记录哪些行/列需要置零
- 优化方案复用矩阵的首行首列作为标记位
- 需要额外变量记录首行首列本身是否需要置零
3.2 螺旋矩阵(LeetCode 54)
边界控制是这类题目的核心难点,Python的实现可以非常优雅:
python复制def spiralOrder(matrix):
res = []
while matrix:
res += matrix.pop(0) # 取首行
if matrix and matrix[0]: # 剩余矩阵非空
for row in matrix:
res.append(row.pop()) # 取每行末尾元素
if matrix: # 取末行并反转
res += matrix.pop()[::-1]
if matrix and matrix[0]: # 取剩余行的首元素
for row in matrix[::-1]:
res.append(row.pop(0))
return res
这种解法模拟了人类直观的螺旋遍历过程:
- 每次处理最外层
- 通过pop操作动态缩小矩阵范围
- 方向切换通过切片和反转实现
时间复杂度分析:
- 每个元素被访问恰好一次
- pop(0)操作在Python中实际是O(n)复杂度
- 整体复杂度为O(n²),对于n×n矩阵来说是最优的
3.3 旋转图像(LeetCode 48)
矩阵旋转的数学本质是转置加反转,Python的矩阵操作堪称教科书级示范:
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 row in matrix:
row.reverse()
为什么这样旋转?
- 转置操作交换行列索引(主对角线对称)
- 水平翻转相当于垂直中轴线对称
- 组合效果就是顺时针90度旋转
验证示例:
code复制原始矩阵:
1 2 3
4 5 6
7 8 9
转置后:
1 4 7
2 5 8
3 6 9
水平翻转后:
7 4 1
8 5 2
9 6 3
4. Python3特有的优化技巧
4.1 利用生成器减少内存占用
在处理大型数组时,传统列表推导式会立即生成完整列表。改用生成器表达式可以显著降低内存消耗:
python复制# 传统写法(立即生成列表)
squares = [x**2 for x in range(1000000)]
# 生成器写法(惰性求值)
squares_gen = (x**2 for x in range(1000000))
在LeetCode环境中,虽然多数题目数据量不大,但这个习惯在真实面试白板编程时能体现内存意识。
4.2 使用collections.defaultdict简化计数
统计元素频率是数组题的常见操作,defaultdict能让代码更简洁:
python复制from collections import defaultdict
def frequency(nums):
freq = defaultdict(int)
for num in nums:
freq[num] += 1
return freq
对比普通字典写法:
python复制freq = {}
for num in nums:
if num not in freq:
freq[num] = 0
freq[num] += 1
4.3 矩阵运算优先考虑NumPy
虽然LeetCode只支持标准库,但在实际面试中如果允许使用NumPy,矩阵操作会变得极其简单:
python复制import numpy as np
matrix = np.array([[1,2],[3,4]])
# 矩阵转置
print(matrix.T)
# 矩阵乘法
print(matrix @ matrix)
即使在不允许用NumPy的情况下,了解这些操作背后的原理也能帮助理解题目本质。
5. 面试实战建议
-
白板编码时先确认输入输出示例
- 明确输入是否可以被修改
- 询问矩阵是否为方形等前提条件
-
二维矩阵的常见考察维度:
- 对角线遍历(LeetCode 498)
- 搜索(LeetCode 240)
- 动态规划(LeetCode 64)
-
当面试官要求优化时,可以依次考虑:
- 时间复杂度能否从O(n²)降到O(nlogn)
- 空间复杂度能否从O(n)降到O(1)
- 是否有位运算等特殊技巧
-
Python3面试中的加分项:
- 正确使用__str__和__repr__
- 了解列表底层实现是动态数组
- 能解释浅拷贝与深拷贝的区别
我在多次面试中总结出一个黄金法则:先给出最直观的解法,再逐步优化。面试官更看重你解决问题的思路,而不仅仅是最终代码。比如在矩阵旋转问题中,可以先提出使用额外空间的方案,再优化到原地操作,这样能完整展示思考过程。
