1. 动态规划核心思想与应用场景
动态规划(Dynamic Programming)是算法设计中解决最优化问题的重要方法。它通过将复杂问题分解为相互重叠的子问题,并存储子问题的解来避免重复计算,从而显著提高算法效率。
1.1 动态规划的本质特征
动态规划适用于具有以下两个关键特征的问题:
- 最优子结构:问题的最优解包含其子问题的最优解
- 重叠子问题:不同的子问题会重复求解相同的更小子问题
以背包问题为例,当我们考虑是否将当前物品放入背包时,需要基于之前物品的选择结果做出决策,这正是动态规划发挥作用的典型场景。
1.2 动态规划的解题框架
标准动态规划解题包含五个关键步骤:
- 确定dp数组及下标含义
- 确定递推公式
- 初始化dp数组
- 确定遍历顺序
- 举例推导验证
这个框架将贯穿我们后续对三个经典问题的解析。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 最后一块石头的重量问题(1049题)
2.1 问题重述与转化
给定一堆石头,每次选择两块粉碎,求最后剩下石头的最小可能重量。这个问题可以转化为经典的背包问题:
如何将石头分成两堆,使两堆的重量差最小?
设总重量为sum,我们需要找到一堆石头,其重量尽可能接近sum/2。这样两堆的重量差(sum - dp[target]) - dp[target] = sum - 2*dp[target]就是最小的剩余重量。
2.2 动态规划解法详解
2.2.1 一维DP实现
python复制class Solution:
def lastStoneWeightII(self, stones):
total_sum = sum(stones)
target = total_sum // 2
dp = [False] * (target + 1)
dp[0] = True # 重量0总是可以达到
for stone in stones:
for j in range(target, stone - 1, -1):
dp[j] = dp[j] or dp[j - stone]
for i in range(target, -1, -1):
if dp[i]:
return total_sum - 2 * i
return 0
关键点解析:
dp[j]表示能否凑出重量j- 内层循环倒序避免重复计算
- 最后从大到小查找最大的可达重量
2.2.2 二维DP实现
python复制class Solutio
