495 字
2 分钟
代码随想录算法训练营第三十一天 | 动态规划 Part04

1049. 最后一块石头的重量 II#

LeetCode 1049. Last Stone Weight II

  • 本质:将所有石头分为两个子集,目标是找到最接近总重量一半的子集重量。
  • 转换为0-1 背包问题:每个石头只能选或不选。
class Solution:
def lastStoneWeightII(self, stones: List[int]) -> int:
sum_weight = sum(stones)
# dp[i][j] 表示前 i 个石头能否组成重量 j 的最大重量
dp = [[0] * (sum_weight // 2 + 1) for _ in range(len(stones) + 1)]
for i in range(1, len(stones) + 1):
cur = stones[i - 1]
for j in range(sum_weight // 2 + 1):
if j >= cur:
# 可以选当前石头
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - cur] + cur)
else:
# 不能选当前石头
dp[i][j] = dp[i - 1][j]
# 最大可达的重量 max_weight,差值即为 total - 2 * max_weight
max_weight = dp[len(stones)][sum_weight // 2]
return sum_weight - max_weight * 2

494. 目标和#

LeetCode 494. Target Sum

  • 转化为回溯 + 记忆化搜索问题。
  • 每个位置尝试 + 或 -,使用备忘录避免重复计算。
class Solution:
def findTargetSumWays(self, nums: List[int], target: int) -> int:
self.memo = {}
if len(nums) == 0:
return 0
return self.dp(nums, 0, target)
def dp(self, nums, i, remain):
# 终止条件:遍历完整个数组
if i == len(nums):
return 1 if remain == 0 else 0
key = f"{i},{remain}"
if key in self.memo:
return self.memo[key]
# 选择:加 nums[i] 或 减 nums[i]
result = self.dp(nums, i + 1, remain - nums[i]) + \
self.dp(nums, i + 1, remain + nums[i])
self.memo[key] = result
return result

474. 一和零#

LeetCode 474. Ones and Zeroes

  • 这是一个三维 0-1 背包问题
  • 状态定义:dp[i][j][k] 表示前 i 个字符串,使用 j 个 0 和 k 个 1 的最大子集大小。
class Solution:
def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
# 初始化三维数组:dp[i][j][k]
dp = [[[0] * (n + 1) for _ in range(m + 1)] for _ in range(len(strs) + 1)]
for i in range(1, len(strs) + 1):
curStr = strs[i - 1]
zeroCount = curStr.count('0')
oneCount = curStr.count('1')
for j in range(m + 1):
for k in range(n + 1):
if j >= zeroCount and k >= oneCount:
# 两种情况:选 or 不选
dp[i][j][k] = max(
dp[i - 1][j - zeroCount][k - oneCount] + 1,
dp[i - 1][j][k]
)
else:
# 容量不足,不能选
dp[i][j][k] = dp[i - 1][j][k]
return dp[len(strs)][m][n]
代码随想录算法训练营第三十一天 | 动态规划 Part04
https://fuwari.vercel.app/posts/code_musings_day_thirty-one/
作者
Jarrett
发布于
2025-07-16
许可协议
CC BY-NC-SA 4.0