1049. 最后一块石头的重量 II 简单理解

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

这道题难在想到任意两块石头重量最小差转化为两堆石头的最小差,从而再联想到01背包问题。

如果你想到了将其转为两堆石头,那为什么又会想到背包问题呢?

思路:假设分为A、B两堆石头,A堆石头重量最大,B堆石头拿总重量减去A堆就得到它的最小重量,它们之间的差也就达到最小。

那A堆石头重量怎么达到最大呢?然后想到A堆石头重量有个理想的最大值,那就是总重量的一半。

而现在每块石头的重量又是不一样的,我们就有了一个目的,怎样分配那些石头去组成A堆,将其重量尽量往理想重量那里靠。

最后,你会发现,A堆石头就是一个背包,理想重量就是背包的容量,石头就是物品,怎样利用这些物品将背包赛的尽量满。

这不就形成了背包问题吗!

public int lastStoneWeightII(int[] stones) {
        int sum = 0;
        int n = stones.length;
        for(int i : stones){
            sum += i;
        }
        //背包的最大容量,也是一个石头堆理想的最大重量
        int target = sum >> 1;
        //背包的滚动数组
        int[] dp = new int[target + 1];

        for (int i = 0; i < n; i++) {
            for (int j = target; j >= 1; j--) {
                if(j >= stones[i]){
                    dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]);
                }
                //如果target容量的背包可以装满,那就无需往后执行了
                //因为一堆石头的重量已经达到最大了,意味着另一堆石头重量达到最小,它们的差也达到最小
                if(dp[j] == target) return sum % 2 == 0 ? 0 : 1;
            }
        }

        //dp[target] 就是最后背包可以装的一个最大重量
        //sum - dp[target] 就是另一堆石头的最小重量
        return (sum - dp[target]) - dp[target];     //返回差值
    }

当然,前提是你肯定要先搞懂01背包问题的思路是怎么样的。

我这里用的是一维滚动数组的方式,还有二维数组的方式。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值