1. 遍历方式选择的本质矛盾
在动态规划(DP)问题中,数组遍历是基础操作却暗藏玄机。我曾在一次LeetCode周赛中因为遍历顺序选择不当,导致原本O(n)的解法退化为O(n^2)。这个问题看似简单,却直接影响着算法的时间复杂度和空间优化可能性。
两种主流遍历方式各有适用场景:
- 索引遍历:通过
for i in range(len(dp))直接操作下标 - 长度遍历:通过
for i in range(n)基于问题规模迭代
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 索引遍历的典型应用场景
2.1 原地修改型DP问题
当DP数组需要原地更新时,索引遍历几乎是唯一选择。比如经典的"打家劫舍"问题:
python复制def rob(nums):
if not nums: return 0
dp = nums.copy()
for i in range(1, len(dp)): # 必须用索引遍历
dp[i] = max(dp[i-1], dp[i] + (dp[i-2] if i>1 else 0))
return dp[-1]
关键点:当后序状态依赖前序状态的原始值时,必须保留原始数组的完整索引空间
2.2 多维状态转移场景
对于二维DP如编辑距离问题,双重索引遍历不可避免:
python复制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])
3. 长度遍历的优势与陷阱
3.1 空间优化型DP
当进行滚动数组优化时,长度遍历更直观。以斐波那契数列为例:
python复制def fib(n):
if n < 2: return n
a, b = 0, 1
for _ in range(2, n+1): # 基于问题规模遍历
a, b = b,
