C语言重构【1049】最后一块石头的重量 II

所有题目源代码:Git地址

题目

有一堆石头,每块石头的重量都是正整数。

每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:

如果 x == y,那么两块石头都会被完全粉碎;
如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。
最后,最多只会剩下一块石头。返回此石头最小的可能重量。如果没有石头剩下,就返回 0。

 

示例:

输入:[2,7,4,1,8,1]
输出:1
解释:
组合 24,得到 2,所以数组转化为 [2,7,1,8,1],
组合 78,得到 1,所以数组转化为 [2,1,1,1],
组合 21,得到 1,所以数组转化为 [1,1,1],
组合 11,得到 0,所以数组转化为 [1],这就是最优值。
 

提示:
1 <= stones.length <= 30
1 <= stones[i] <= 1000

方案:

  • 背包问题的变种
class Solution
{
    
    
public:
    int lastStoneWeightII(vector<int> &stones)
    {
    
    
        //将这堆石头分成大小尽量相近的两堆
        //自己先求出target,转化成背包问题
        int len = stones.size();
        if (len == 1)
            return stones[0];
        int sum = 0;
        for (int i = 0; i < len; i++)
        {
    
    
            sum += stones[i];
        }
        int target = sum / 2;
        vector<int> dp(target + 1, 0);
        //接下来就是背包问题了
        for (int i = 0; i < len; i++)
        {
    
    
            int val = stones[i];
            for (int j = target; j >= val; j--)
            {
    
    
                dp[j] = max(dp[j], dp[j - val] + val);
            }
        }
        return sum - 2 * dp[target];
    }
};
复杂度计算
  • 时间复杂度:O(n*target)
  • 空间复杂度:O(target)

猜你喜欢

转载自blog.csdn.net/symuamua/article/details/114592172