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 背包。

相关推荐
wubba lubba dub dub7501 小时前
第四十九周学习周报
人工智能·算法·机器学习
Java_2017_csdn2 小时前
ComplexKeysShardingAlgorithm 小结
java·大数据·算法
海梨花2 小时前
快手面试高频算法题
java·算法·面试
lqqjuly2 小时前
超分辨率算法深度解析(Super-Resolution Algorithms)
算法
Zik----3 小时前
保研面试拷打
面试·职场和发展
嵌入式老牛3 小时前
液晶段码(米/日字格)识别—倾斜校正
opencv·算法·仿射变换
luj_17683 小时前
残熵算法:风险缓冲与效率优化的融合
c语言·开发语言·网络·经验分享·算法
oddsand14 小时前
pgvector 三大相似度算法
人工智能·算法·机器学习
运筹vivo@4 小时前
LeetCode 2574. 左右元素和的差值
算法·leetcode·职场和发展·每日一题