力扣第1049题 最后一块石头的重量Il c++ 动态规划(01背包)

这篇具有很好参考价值的文章主要介绍了力扣第1049题 最后一块石头的重量Il c++ 动态规划(01背包)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题目

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

中等

相关标签

有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。

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

  • 如果 x == y,那么两块石头都会被完全粉碎;
  • 如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x

最后,最多只会剩下一块 石头。返回此石头 最小的可能重量 。如果没有石头剩下,就返回 0

示例 1:

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

示例 2:

输入:stones = [31,26,33,21,40]
输出:5

提示:

  • 1 <= stones.length <= 30
  • 1 <= stones[i] <= 100

思路和解题方法

使用了 0-1 背包问题的思想,通过动态规划的方式求解。

具体思路如下:

  1. 首先,计算所有石头的总重量 sum
  2. 然后,将问题转化为将石头分成两堆,使得两堆的重量尽可能接近 sum/2
  3. 创建一个大小为 15001 的动态规划数组 dp,用于记录容量为 j 的背包所能装载的最大重量。
  4. 使用双重循环遍历石头数组 stones 和背包容量 j,进行动态规划的状态转移。
  5. 在每次状态转移时,比较当前背包容量 j 能够装载的最大重量 dp[j] 和将当前石头放入背包后所能得到的重量 dp[j - stones[i]] + stones[i],取较大值更新 dp[j]
  6. 最后,返回两堆石头的重量差值,即 sum - dp[target] - dp[target]

复杂度

        时间复杂度:

                O(n*m)

        时间复杂度为 O(n * m)。

其中 n 是石头的数量,m 是石头总重量的一半。这是因为代码中使用了两层循环,外层循环遍历石头数组,内层循环遍历背包容量。对于每个背包容量,都需要进行一次状态转移操作,因此总共需要进行 n * m 次状态转移。

        空间复杂度

                O(m)

        空间复杂度为 O(m)。

        其中 m 是石头总重量的一半。这是因为代码中创建了一个大小为 15001 的动态规划数组 dp,用于记录不同背包容量下的最大重量。由于背包容量的最大值为石头总重量的一半,因此数组 dp 的大小为 m+1,即 15001。因此,所需的额外空间随着石头总重量的增加而增加,但是与石头的数量无关。

需要注意的是,代码中使用了一个固定大小的动态规划数组 dp,这是因为题目给定了石头的最大数量为 30,每块石头的重量最大为 100。根据题目的限制条件,可以确定石头总重量的上限为 3000,因此背包容量的上限为 1500。为了保证数组 dp 能够覆盖所有可能的背包容量,将其大小设置为 15001。如果题目的限制条件发生变化,可能需要调整数组 dp 的大小以适应新的情况。

c++ 代码

int lastStoneWeightII(vector<int>& stones) {
    vector<int> dp(15001, 0); // 创建一个大小为 15001 的动态规划数组 dp,初始值都为 0
    int sum = 0; // 计算所有石头的总重量
    for (int i = 0; i < stones.size(); i++) {
        sum += stones[i];
    }
    int target = sum / 2; // 目标是将石头分为两堆,使得两堆的重量尽可能接近 sum/2

    for (int i = 0; i < stones.size(); i++) {
        for (int j = target; j >= stones[i]; j--) {
            // 动态规划的核心逻辑
            // dp[j] 表示容量为 j 的背包所能装载的最大重量
            // dp[j-stones[i]]+stones[i] 表示将当前石头放入容量为 j 的背包中所能得到的重量
            dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);
        }
    }

    return sum - dp[target] - dp[target]; // 返回两堆石头的重量差值
}

简洁写法(使用库函数做加法)

class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        vector<int> dp(15001,0);
        int sum = accumulate(stones.begin(), stones.end(), 0);
        int target = sum/2;
        for(int i = 0;i<stones.size();i++)
            for(int j = target;j>=stones[i];j--)
                dp[j] = max(dp[j],dp[j-stones[i]]+stones[i]);
        return sum - dp[target] - dp[target];
    }
};

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。文章来源地址https://www.toymoban.com/news/detail-741268.html

到了这里,关于力扣第1049题 最后一块石头的重量Il c++ 动态规划(01背包)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Leetcode 1049 最后一块石头的重量II

    题意理解 :         有一堆石头,用整数数组  stones  表示。其中  stones[i]  表示第  i  块石头的重量。         每一回合,从中选出 任意两块石头 ,然后将它们一起粉碎。假设石头的重量分别为  x  和  y ,且  x = y 。         思路转化:我们可以将题目转换为

    2024年01月16日
    浏览(38)
  • LeetCode 1049 最后一块石头的重量 II

    题目: 有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x = y。那么粉碎的可能结果如下: 如果 x == y,那么两块石头都会被完全粉碎; 如果 x != y,那么重

    2024年02月05日
    浏览(44)
  • Leet code1049 最后一块石头的重量II

    1049 最后一块石头的重量II 【问题描述】 有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合,从中选出 任意两块石头 ,然后将它们一起粉碎。假设石头的重量分别为 x 和 y ,且 x = y 。那么粉碎的可能结果如下: 如果 x == y ,那么两块石头

    2024年02月13日
    浏览(43)
  • 【LeetCode题目详解】第九章 动态规划 part05 1049. 最后一块石头的重量 II 494. 目标和 474.一和零(day43补)

    有一堆石头,用整数数组  stones 表示。其中  stones[i] 表示第 i 块石头的重量。 每一回合,从中选出 任意两块石头 ,然后将它们一起粉碎。假设石头的重量分别为  x 和  y ,且  x = y 。那么粉碎的可能结果如下: 如果  x == y ,那么两块石头都会被完全粉碎; 如果  x != y

    2024年02月09日
    浏览(38)
  • 【Day43】代码随想录之动态规划0-1背包_1049. 最后一块石头的重量 II_494. 目标和_ 474.一和零

    动态规划理论基础 动规五部曲: 确定dp数组 下标及dp[i] 的含义。 递推公式:比如斐波那契数列 dp[i] = dp[i-1] + dp[i-2]。 初始化dp数组。 确定遍历顺序:从前到后or其他。 打印。 出现结果不正确: 打印dp日志和自己想的一样:递推公式、初始化或者遍历顺序出错。 打印dp日志和

    2024年02月22日
    浏览(49)
  • 【算法与数据结构】1049、LeetCode 最后一块石头的重量 II

    所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。    思路分析 :本题需要得到石头之间两两粉碎之后的最小值,那么一个简单的思路就是将这堆石头划分成大小相近的两小堆石头,然后粉碎,这样得到的结果必然是最优值。那么如何划分呢?我

    2024年01月21日
    浏览(47)
  • ( 背包问题) 1049. 最后一块石头的重量 II ——【Leetcode每日一题】

    难度:中等 有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合,从中选出 任意两块石头 ,然后将它们一起粉碎。假设石头的重量分别为 x 和 y ,且 x = y 。那么粉碎的可能结果如下: 如果 x == y ,那么两块石头都会被完全粉碎; 如果 x !=

    2024年02月08日
    浏览(51)
  • 代码随想录Day36 动态规划05 LeetCode T1049最后一块石头的重量II T494 目标和 T474 一和零

    理论基础  : 代码随想录Day34 LeetCode T343整数拆分 T96 不同的二叉搜索树-CSDN博客 1.明白dp数组的含义 2.明白递推公式的含义 3.初始化dp数组 4.注意dp数组的遍历顺序 5.打印dp数组排错 题目链接:1049. 最后一块石头的重量 II - 力扣(LeetCode) 这题我们仍然采用动规五部曲来写,这题和

    2024年02月06日
    浏览(41)
  • day43 | 1049. 最后一块石头的重量 II、494. 目标和、474.一和零

    目录: 1049. 最后一块石头的重量 II 有一堆石头,用整数数组  stones  表示。其中  stones[i]  表示第  i  块石头的重量。 每一回合,从中选出 任意两块石头 ,然后将它们一起粉碎。假设石头的重量分别为  x  和  y ,且  x = y 。那么粉碎的可能结果如下: 如果  x == y ,那

    2024年02月12日
    浏览(34)
  • Day43|leetcode 1049.最后一块石头的重量II、494.目标和、474.一和零

    题目链接:1049. 最后一块石头的重量 II - 力扣(LeetCode) 视频链接:动态规划之背包问题,这个背包最多能装多少?LeetCode:1049.最后一块石头的重量II_哔哩哔哩_bilibili 有一堆石头,每块石头的重量都是正整数。 每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设

    2024年02月10日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包