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

相关推荐
地平线开发者2 小时前
J6B vio scenario sample
算法
BothSavage14 小时前
Trae远程开发中DeepSeek自定义模型4054错误的排查与修复
算法
小林ixn14 小时前
从暴力到KMP:一道题彻底搞懂字符串匹配的前世今生
算法
烬羽15 小时前
字符串算法入门:从反转字符串到回文判断,面试不再慌
算法·面试
先吃饱再说1 天前
判断回文字符串,从一行代码到双指针优化
算法
黄敬峰1 天前
深入理解算法核心:从递归思想、数组扁平化到快速排序
算法
得物技术1 天前
从狂野代码到按目标生产:得物推荐 AI Harness 的工程化实践|AICon 演讲整理
人工智能·算法·架构
AI小老六2 天前
SkillOpt 架构拆解:把 Skill 文本当参数,用执行轨迹训练 Agent
后端·算法·ai编程