首页 > 其他分享 >代码随想录Day36 | 1049.最后一块石头的重量 II,494.目标和,474.一和零

代码随想录Day36 | 1049.最后一块石头的重量 II,494.目标和,474.一和零

时间:2025-01-15 16:33:22浏览次数:3  
标签:背包 target nums Day36 sum 随想录 II int dp

代码随想录Day36 | 1049.最后一块石头的重量 II,494.目标和,474.一和零

1049.最后一块石头的重量

视为背包问题,求解 sum / 2 容量背包能装下的最大重量

返回的是 这一部分石头 与 另一部分 的差值的绝对值

代码即为经典的01背包问题

class Solution {
    public int lastStoneWeightII(int[] stones) {
        if (stones.length == 1) return stones[0];
        // 视为背包问题,求解 sum / 2 容量背包能装下的最大重量
        // 返回的是 这一部分石头 与 另一部分 的差值的绝对值
        int sum = Arrays.stream(stones).sum();
        int target = sum / 2;
        int[] dp = new int[target + 1];

        // dp[i][j]的定义为:
        // 从 0-i 取石头,装进容量为 j 的背包可获得的最大重量
        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];
    }
}

494.目标和

与前几道的01背包问题不同,求的是最大价值数,这道题求的是装满背包的种类数(排列组合数)

在状态转移时仍然是考虑 **取 或 不取数字nums[i] **的两种情况。

可以先写出二维dp的代码,这样便于理解,然后优化为一维dp

class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        // 题意是将数字分为两部分,它们和的差值是target
        // left + right = sum, left - right = target
        // left = (sum + target) / 2
        // 而且求的是种类数
        // 转化为背包问题,求装满 (sum + target) / 2 的种类数
        int sum = Arrays.stream(nums).sum();
        // 总和都没有 target 绝对值大,无解
        if (sum < Math.abs(target)) return 0;
        // bag 为小数,无解
        if ((sum + target) % 2 != 0) return 0;
        
        int bag = (sum + target) / 2; 
        // dp[i][j]定义:
        // 从 0-i 中取数字,能装满容量为 j 的背包的种类数(排列组合数)     
        int[][] dp = new int[nums.length][bag + 1];

        // 初始化第一行
        if (nums[0] <= bag)
            dp[0][nums[0]] = 1;

        // 初始化第一列,根据 0 的个数取值
        // 若是两个0,则每个0取或不取,2的2次
        int zeros = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == 0) zeros++;
            dp[i][0] = (int) Math.pow(2, zeros);
        }

        for (int i = 1; i < nums.length; i++) {
            for (int j = 1; j <= bag; j++) {
                if (nums[i] > j)
                    dp[i][j] = dp[i - 1][j];
                else
                    // 状态转移:取 或 不取数字nums[i]
                    dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i]];
            }
        }

        return dp[nums.length - 1][bag];
    }
}

class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        // 题意是将数字分为两部分,它们和的差值是target
        // left + right = sum, left - right = target
        // left = (sum + target) / 2
        // 而且求的是种类数
        // 转化为背包问题,求装满 (sum + target) / 2 的种类数
        int sum = Arrays.stream(nums).sum();
        // 总和都没有 target 绝对值大,无解
        if (sum < Math.abs(target)) return 0;
        // bag 为小数,无解
        if ((sum + target) % 2 != 0) return 0;
        
        int bag = (sum + target) / 2; 
        // dp[i][j]定义:
        // 从 0-i 中取数字,能装满容量为 j 的背包的种类数(排列组合数)
        // 只用到上一行数据,优化为一维数组,每一行从后往前遍历    
        int[] dp = new int[bag + 1];
        dp[0] = 1;

        for (int i = 0; i < nums.length; i++) {
            for (int j = bag; j >= nums[i]; j--) {
                dp[j] += dp[j - nums[i]];
            }
        }

        return dp[bag];
    }
}

474.一和零

难点在于将问题转换为动态规划问题:

  • 视为01背包问题,但是物品的价值有0的个数和1的个数两个维度
  • 循环时,遍历物品、背包的0容量、1容量 三个维度
  • 按照标准dp就应该是三维dp,优化为二维dp

然后就是背包问题的代码形式

class Solution {
    public int findMaxForm(String[] strs, int m, int n) {
        // dp[i][j]定义:
        // 最多包含 i个0 和 j个1 时,strs的最大子集长度
        int[][] dp = new int[m + 1][n + 1];
        // 这道题可以视为01背包,但是物品的价值有0和1两个维度
        // 循环时,遍历物品、背包的0容量、1容量 三个维度
        // dp本来应该是三维,优化到二维,从后往前遍历
        for (String str : strs) {
            // 统计当前str的 0,1 个数
            int ones = 0, zeros = 0;
            for (char c : str.toCharArray()) {
                if (c == '1') ones++;
                else zeros++;
            }
            for (int i = m; i >= zeros; i--) {
                for (int j = n; j >= ones; j--) {
                    // 状态转移方程:选 或 不选 当前str 两种情况
                    // 选的话 次数 +1
                    dp[i][j] = Math.max(dp[i][j], dp[i - zeros][j - ones] + 1);
                }
            }
        }
        return dp[m][n];
    }
}

标签:背包,target,nums,Day36,sum,随想录,II,int,dp
From: https://blog.csdn.net/weixin_43992121/article/details/145162935

相关文章

  • STM32F1基于HAL库的学习记录实用使用教程分享(四、OLED IIC)
    往期内容STM32F1基于HAL库的学习记录实用使用教程分享(一、GPIO_Output)STM32F1基于HAL库的学习记录实用使用教程分享(二、GPIO_Input按键)STM32F1基于HAL库的学习记录实用使用教程分享(三、外部中断按键)文章目录往期内容前言一、IIC1.概念2.IIC作用3.IIC的特点II......
  • 2025/1/15 力扣每日一题(3066. 超过阈值的最少操作数 II)
    来源:LeetCode链接:https://leetcode.cn/problems/minimum-operations-to-exceed-threshold-value-ii/description/?envType=daily-question&envId=2025-01-15题目:给你一个下标从0开始的整数数组nums和一个整数k。一次操作中,你将执行:选择nums中最小的两个整数x和y......
  • 如何在IIS中设置网站文件和图片的防盗链功能?
    在互联网环境中,防盗链是保护网站资源不被其他网站非法引用的重要措施。通过设置防盗链,可以有效防止其他网站直接链接到您的图片、视频等资源,从而节省带宽并保护版权。本文将详细介绍如何在IIS(InternetInformationServices)中设置网站文件和图片的防盗链功能。一、准备工作安装......
  • 如何解决IIS 7.5 中无扩展名文件访问导致的404错误?
    在使用IIS7.5时,如果尝试访问没有扩展名或后缀的文件(例如 index 而不是 index.html),可能会遇到404错误提示,表明服务器找不到该文件。这是因为IIS默认情况下不支持无扩展名文件的直接访问。为了解决这个问题,我们需要配置IIS以正确处理这些请求。解决方案要使IIS支持......
  • 【Leetcode 每日一题】3066. 超过阈值的最少操作数 II
    问题背景给你一个下标从000开始的整数数组num......
  • js 调用 IIS部署的 WebAPI 相关配置
    1.跨域问题处理需要在web.config添加节点<system.webServer><httpProtocol><customHeaders><addname="Access-Control-Allow-Origin"value="*"/><addname="Access-Control-Allow-Headers"......
  • ryujin 1.2.78下载(龙神模拟器),配置19.0的key和对应固件,解决amiibo API错误(需要翻墙vpn)
    1.下载不废话Release1.2.78·Ryubing/Ryujinx·GitHub,找对应的版本下载下载后解压得到publish文件夹,打开里面的Ryujinx.exe,会报错,别管先挂着,接着看步骤22.配置switch的key和固件推荐(不用vpn):下面步骤2.1和2.2 key和固件的下载要使用vpn,你可以直接用夸克打开下面......
  • LeetCode:40.组合总和II
    跟着carl学算法,本系列博客仅做个人记录,建议大家都去看carl本人的博客,写的真的很好的!代码随想录LeetCode:40.组合总和II给定一个候选人编号的集合candidates和一个目标数target,找出candidates中所有可以使数字和为target的组合。candidates中的每个数字在每......
  • 代码随想录:验证二叉搜索树
    二叉搜索树的中序遍历结果是一个递增的数组为了省空间可以用一个变量记录上一次的数字我一开始设置上一次的为null,结果c++中int为null时实际为0,所以要用最小值/***Definitionforabinarytreenode.*structTreeNode{*intval;*TreeNode*left;*......
  • 如何在不重启IIS的情况下回收IIS程序池?
    问题描述:在服务器管理中,有时需要回收IIS程序池以释放资源或解决某些问题,但又不想重启整个IIS服务。请问如何在不重启IIS的情况下回收IIS程序池?具体操作步骤是什么?如果通过远程桌面连接到服务器进行操作,需要注意哪些事项?答案:您好,回收IIS程序池而不重启IIS是一个常见的操作,尤其是......