首页 > 其他分享 >1049. 最后一块石头的重量 II(leetcode)

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

时间:2024-09-02 20:46:56浏览次数:3  
标签:stones 重量 target int 1049 II sum leetcode dp

https://leetcode.cn/problems/last-stone-weight-ii/description/

思路较为巧妙的dp题,关键点在于如何将问题转化为01背包,有点贪心的思想
主要是划分为两堆尽可能相等的石碓,然后判断能否凑出这个偏小的石碓(若干石头中选,能否选出这个价值)
这里根据f[i]的定义可以有两种做法,1.f[i][j]表示前i个石头中选能否凑出重量为j的选法,类型是布尔
2.f[i][j]表示前i个石头中选,选出重量<=j的选法的最大价值,这里的价值也是重量这个数值

class Solution {
    public int lastStoneWeightII(int[] stones) {
        // 由于要两两相撞,因此需要分成两堆尽可能相等的石碓来相互撞
        // 这样就知道目标target是多少了
        // 如此就转换为01背包问题了,在若干石头中选,选出重量为目标的选法的 最大重量
        // 这里重量是价值和体积
        // f[i][j]表示前i个石头中选能否凑出重量为j的重量,那么答案就是f[n][target]
        // f[i][j] = f[i-1][j] || f[i-1][j-stones[i]]
        // f[0][0] = true; // 凑出重量为0的石头显然可以
        int sum = 0;
        for (int s : stones)sum += s;
        int target = sum / 2;
        boolean[][] f = new boolean[stones.length+10][target + 10];
        f[0][0]=true; // 0不是第一个石头,而是一个石头都不选

        for (int i = 1; i <= stones.length; i++) 
        {
            for (int j = 0; j <= target; j++) 
            {
                // 这里stones下标需要偏移一位,因为f[0][0]没选石头,因此stone[i]表示第i+1块石头
                if(j>=stones[i-1]) 
                    f[i][j] = f[i-1][j] || f[i-1][j-stones[i-1]];
                else f[i][j]=f[i-1][j];
            }
        }
        // 倒序给出重量最大的答案
        for(int i=target;;i--)
            if(f[stones.length][i])return sum-2*i;
    }
}
class Solution {
    public int lastStoneWeightII(int[] stones) {
        // 由于要两两相撞,因此需要分成两堆尽可能相等的石碓来相互撞
        // 这样就知道目标target是多少了
        // 如此就转换为01背包问题了,在若干石头中选,选出重量为目标的选法的 最大重量
        // 这里重量是价值和体积
        int sum = 0;
        for (int s : stones) {
            sum += s;
        }

        int target = sum / 2;
        //初始化,dp[i][j]为可以放0-i物品,背包容量为j的情况下背包中的最大价值
        int[][] dp = new int[stones.length][target + 1];
        //dp[i][0]默认初始化为0
        //dp[0][j]取决于stones[0]
        for (int j = stones[0]; j <= target; j++) {
            dp[0][j] = stones[0];
        }

        for (int i = 1; i < stones.length; i++) {
            for (int j = 0; j <= target; j++) {//注意是等于
                if (j >= stones[i]) {
                    //不放:dp[i - 1][j] 放:dp[i - 1][j - stones[i]] + stones[i]
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - stones[i]] + stones[i]);
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }

        return sum - 2*dp[stones.length - 1][target];
    }
}

 

标签:stones,重量,target,int,1049,II,sum,leetcode,dp
From: https://www.cnblogs.com/lxl-233/p/18393509

相关文章

  • 20240902_171049 mysql 填空题 ddl表
    创建一个名为tb的表creatatabletb()创建一个名为tb的表,先判断再创建createtableifnotexiststb()新建一个student表,拷备teacher表的结构createtablestudentliketeacher删除一个名为student的表droptablestudent删除名为student的表,先判断再删除droptableif......
  • Leetcode——1.合并有序数组
    给你两个按非递减顺序排列的整数数组nums1_和nums2,另有两个整数m和n,分别表示nums1和nums2中的元素数目。请你合并nums2_到nums1中,使合并后的数组同样按非递减顺序排列。注意:最终,合并后数组不应由函数返回,而是存储在数组nums1中。为了应对这种情况,nums1的初......
  • 每日一题:Leetcode-224 基本计算器
    力扣题目解题思路java代码力扣题目:给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。示例1:输入:s="1+1"输出:2示例2:输入:s="2-1+2"输出:3示例3:输入:s......
  • 【LeetCode】两数之和
    题目:在数组中找到2个数之和等于给定值的数字,结果返回2个数字在数组中的下标。要求时间复杂度为 O(n)。解题分析:作者:halfrost链接:https://leetcode.cn/leetbook/read/leetcode-cookbook/5lu4og/顺序扫描数组,对每一个元素,在map中找能组合给定值的另一半数字,如果找......
  • Leetcode37-和相等的子数组(2395)
    1、题目给你一个下标从0开始的整数数组nums,判断是否存在两个长度为2的子数组且它们的和相等。注意,这两个子数组起始位置的下标必须不相同。如果这样的子数组存在,请返回true,否则返回false。子数组是一个数组中一段连续非空的元素组成的序列。示例1:输入......
  • 122.买股票的最佳时机II
    122.买股票的最佳时机II给你一个整数数组prices,其中prices[i]表示某支股票第i天的价格。在每一天,你可以决定是否购买和/或出售股票。你在任何时候最多只能持有一股股票。你也可以先购买,然后在同一天出售。返回你能获得的最大利润。示例1:输入:prices=......
  • 代码随想录day48 || 739, 每日温度 496, 下一个更大元素 I 503, 下一个更大元素II
    739每日温度funcdailyTemperatures(temperatures[]int)[]int{ //双指针 varres=make([]int,len(temperatures)) fori:=0;i<len(temperatures);i++{ forj:=i+1;j<len(temperatures);j++{ iftemperatures[j]>temperatures[i]{ res[i]=j......
  • leetcode 75. Sort Colors & 三路快速排序
    leetcode75.SortColors&三路快速排序只有0和1的情况在这种简化情况下,我们只需要顺序遍历数组,遇到0就放到前面即可。classlocalExperiment{public:voidsort01(std::vector<int>&nums){intzero_ptr=0;for(inti=0;i<nums.size();......
  • 二叉树的直径(LeetCode)
    题目给你一棵二叉树的根节点,返回该树的 直径 。二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root 。两节点之间路径的 长度 由它们之间边数表示。解题classTreeNode:def__init__(self,val=0,left=......
  • 设置IIS支持ashx
    打开【处理程序映射】默认界面如下(是不支持处理ashx的):如果需要设置能处理ashx,需要开启ASP.NET4.8再打开【处理程序映射】,如下: ......