LeetCode 1049:最后一块石头的重量 II —— 题解 ✅

LeetCode 1049:最后一块石头的重量 II ------ 题解 ✅

🔗 题目链接

👉 https://leetcode.cn/problems/last-stone-weight-ii/


📖 内容概要

有一堆石头,每块石头的重量为 stones[i]

每次任选两块石头 xy,将它们一起粉碎,剩余重量为 |x - y|

求最后剩下石头的 最小可能重量

✅ 0/1 背包

✅ 分割等和子集的变形

✅ 面试高频 / medium思维题


💡 解题思路(核心)

一、关键转化(非常重要)

最终剩余重量最小 ⇔ 把石头分成两堆,使两堆总重量尽可能接近

因为:

复制代码
最终重量 = |sumA - sumB|

sumA ≈ sumB 时,结果最小。


二、问题等价于

从数组中选取若干石头,使其总和不超过 sum / 2,且尽可能大

👉 典型的 0/1 背包问题


三、DP 定义

java 复制代码
dp[j] = 容量为 j 的背包,能装的最大重量

目标:

java 复制代码
max(dp[target])

四、状态转移方程

java 复制代码
dp[j] = max(
    dp[j],
    dp[j - stones[i]] + stones[i]
)

✅ 每个石头只能用一次

✅ 必须 倒序遍历


五、最终答案

java 复制代码
sum - dp[target] - dp[target]
= sum - 2 × dp[target]

✅ AC 代码(Java)

java 复制代码
class Solution {
    public int lastStoneWeightII(int[] stones) {
        int sum = 0;
        for (int x : stones) {
            sum += x;
        }

        int target = sum / 2;
        int[] dp = new int[1505];

        // 0/1 背包
        for (int i = 0; i < stones.length; i++) {
            for (int j = target; j >= stones[i]; j--) {
                dp[j] = Math.max(
                    dp[j],
                    dp[j - stones[i]] + stones[i]
                );
            }
        }

        return sum - dp[target] - dp[target];
    }
}

⏱️ 复杂度分析

指标 复杂度
时间复杂度 O(n × sum)
空间复杂度 O(sum)

🔍 与「分割等和子集」的关系

题目 目标
416. 分割等和子集 是否存在 sum/2
1049. 最后一块石头 II 最接近 sum/2 的最大值

✅ 本题是 416 题的"最值版"


✅ 一句话总结

把石头分成两堆,使重量差最小,等价于在 sum/2 的限制下做 0/1 背包。

相关推荐
GuWenyue4 小时前
传统Agent工具两大痛点!300行代码落地MCP跨语言工具,彻底解耦LLM与工具
前端·人工智能·算法
我叫洋洋5 小时前
C ++ [ hello world ]
c语言·c++·算法
奋发向前wcx7 小时前
y1,y2总复习笔记5 2026.7.19
数据结构·笔记·算法
战族狼魂10 小时前
高频面试题精选:分治与AI Agent架构
人工智能·算法·大模型·大语言模型
李剑一10 小时前
你用过网易的将军令嘛?它底层实现账号保护的原理相当简单粗暴
算法
Scott9999HH10 小时前
告别流量波动玄学!从法拉第电磁定律到底层 C/C++ 流量累积算法,深度解密工业级电磁流量计选型与开发
c语言·c++·算法
中达瑞和-高光谱·多光谱10 小时前
1nm到8nm光谱分辨率,你的应用该选哪款光谱相机?
算法·高光谱·高光谱相机
香辣牛肉饭11 小时前
【算法】动态规划 最长公共子序列(LCS)
经验分享·笔记·算法·动态规划
旖-旎12 小时前
LeetCode 279:完全平方数(完全背包)—— 题解
c++·算法·leetcode·动态规划·背包问题