代码随想录Day36 动态规划05 LeetCode T1049最后一块石头的重量II T494 目标和 T474 一和零

这篇具有很好参考价值的文章主要介绍了代码随想录Day36 动态规划05 LeetCode T1049最后一块石头的重量II T494 目标和 T474 一和零。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言 : 动规五部曲

理论基础  : 代码随想录Day34 LeetCode T343整数拆分 T96 不同的二叉搜索树-CSDN博客

1.明白dp数组的含义

2.明白递推公式的含义

3.初始化dp数组

4.注意dp数组的遍历顺序

5.打印dp数组排错文章来源地址https://www.toymoban.com/news/detail-742023.html

LeetCode T1049 最后一块石头的重量II

题目链接:1049. 最后一块石头的重量 II - 力扣(LeetCode)

代码随想录Day36 动态规划05 LeetCode T1049最后一块石头的重量II T494 目标和 T474 一和零,代码随想录,数据结构,Java学习,动态规划,leetcode,算法

题目思路:

这题我们仍然采用动规五部曲来写,这题和昨天的那一道分割等和子集类似,我们先对数组求和得到sum,然后取其的一半+1作为dp数组的大小,最后我们只需要求得sum/2作为容量的背包能装的最大容量,用sum减去两倍的dp[sum/2]即可,有人问为什么这样做,我举个例子

代码随想录Day36 动态规划05 LeetCode T1049最后一块石头的重量II T494 目标和 T474 一和零,代码随想录,数据结构,Java学习,动态规划,leetcode,算法

为什么要减去两倍的dp[sum/2]呢,其实就是求两边到中间的距离的,因为是左边和右边所以减了两次

想明白了这个,我们开始使用动规五部曲来操作了

1.明白dp数组的含义

dp[j]的含义仍然是j容量的背包能装的最大价值,这里的最大价值也就是最大重量了

2.明白递推公式的含义

这里的stones的价值和重量是相等的

dp[j] = Math.max(dp[j],dp[j-stones[i]]+stones[j])

有人始终不明白这里的dp[j]后面为什么求dp[j]和dp[j-stones[i]]+stones[j]的最大值,为啥跟自己求最大值,其实这里后面的dp[j]还保存了上一层的dp[j]的大小,因为没有被更新过,所以其实不是跟自己比

3.初始化dp数组

这里因为石头的重量都是大于0的,我们全部初始化为0即可

4.注意dp数组的遍历顺序

先遍历物品,后遍历背包即可,不明白的看我的上一篇博客

代码随想录Day34 LeetCode T343整数拆分 T96 不同的二叉搜索树-CSDN博客

5.打印dp数组排错

如果遇到所求不符合了,可以去idea打印出数组来查看,这里建议使用二维数组的方式查看,更加直观

题目代码:(一维数组版本)

class Solution {
    public int lastStoneWeightII(int[] stones) {
        int sum = 0;
        for(int i: stones){
            sum+=i;
        }
        int  target = sum/2;
        int[] dp = new int[target+1];
        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];

    }
}

题目代码:(二维数组版本)

class Solution {
    public int lastStoneWeightII(int[] stones) {
        int sum = 0;
        for(int i: stones){
            sum+=i;
        }
        int  target = sum/2;
        int[][] dp = new int[stones.length][target+1];
        for(int i = stones[0];i<=target;i++){
            dp[0][i] = stones[0];
        }
        for(int i = 1;i<stones.length;i++){
            for(int j = 1;j<=target;j++){
                //不放
                if(j<stones[i]){
                    dp[i][j] = dp[i-1][j];
                }
                //放
                else{
                    dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-stones[i]]+stones[i]);
                }
            }
        }
        return sum-dp[stones.length-1][target]*2;

    }
}

LeetCode T494 目标和

题目链接:494. 目标和 - 力扣(LeetCode)

代码随想录Day36 动态规划05 LeetCode T1049最后一块石头的重量II T494 目标和 T474 一和零,代码随想录,数据结构,Java学习,动态规划,leetcode,算法

题目思路:

我们也将数组按正负号划分为两个阵营,此时我们是不是只需要求一边的结果,另一边自然而然就确定了,所以这道题我们就有这样两个表达式

left//表示正的阵营
right//表示负的阵营
left + right = sum
left - right = target
left = (target+sum)/2

这里我们就知道了背包的容量为left的大小对应的表达式

这里如果我们的所求target>sum或者小于-sum都是不可能达成的

还有如果遇见target和sum的和为奇数也是不可能的,直接返回0,这是因为奇数/2是向下取整的,举个例子:

假如我的nums是[1,1,1,1,1],要求得到2

这里left明显等于3

而三个1加上两个-1得到是1,并不符合题意,实际上这个选择是无解的

接下来我们继续按照动规五部曲来走一遍

1.明白dp数组的含义

这里的dp[j]表示,容量为j的背包装满有多少种方法

2.明白递推公式的含义

dp[j] +=dp[j-nums[i]]

因为这里要求方法有多少种,举个例子

dp[5] = dp[4] + 1 其实和斐波那契数列和爬楼梯有点类似,可以相成到达5的方法数就是4的方法数+后面nums[j-nums[i]]的方法数

  • 已经有一个1(nums[i]) 的话,有 dp[4]种方法 凑成 容量为5的背包。
  • 已经有一个2(nums[i]) 的话,有 dp[3]种方法 凑成 容量为5的背包。
  • 已经有一个3(nums[i]) 的话,有 dp[2]中方法 凑成 容量为5的背包
  • 已经有一个4(nums[i]) 的话,有 dp[1]中方法 凑成 容量为5的背包
  • 已经有一个5 (nums[i])的话,有 dp[0]中方法 凑成 容量为5的背包
  • 实际上求dp[5],就是把他们都累加起来

3.初始化dp数组

这里初始化dp[0] = 1,我们不要根据字面关系去理解,直接带入上面的公式理解

left = (target+sum)/2,此时left = 0,这就是一种方法

所以dp[0]要初始化为1而不是0,因为后面都得靠dp[0]推导出来,如果它为0后面的结果都是0

4.注意dp数组的遍历顺序

先遍历物品,后遍历背包

5.打印dp数组排错

题目代码:

class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        int sum = 0;
        for(int i:nums){
            sum += i;
        }
        if(target>sum || target<-sum){
            return 0;
        }
        if((target + sum) % 2 == 1){
            return 0;
        }
        int bagSize = (target+sum)/2;
        int[] dp = new int[bagSize+1];
        dp[0] = 1;
        for(int i = 0;i<nums.length;i++){
            for(int j=bagSize;j>=nums[i];j--){
                dp[j] += dp[j-nums[i]];
            }
        }
        return dp[bagSize];

    }
}

LeetCode T474 一和零

题目链接:474. 一和零 - 力扣(LeetCode)

代码随想录Day36 动态规划05 LeetCode T1049最后一块石头的重量II T494 目标和 T474 一和零,代码随想录,数据结构,Java学习,动态规划,leetcode,算法

题目思路:

代码随想录Day36 动态规划05 LeetCode T1049最后一块石头的重量II T494 目标和 T474 一和零,代码随想录,数据结构,Java学习,动态规划,leetcode,算法

这道题也是一个背包问题,虽然有点抽象,下面我们开始用动规五部曲来分析

1.明白dp数组的含义

这里的dp数组的含义就是m个0和n个1能包含的最大子集,也就是能装下m个0和n个1的背包能存放的最大物品数

2.明白递推公式的含义

我们从最初的0-1背包开始递推

dp[j] = Math.max(dp[j],dp[j - weight[i]]+value[i])

这里我们的重量其实就是i和j的个数,我们使用x代表这个物品中的'0'的个数,y代表1的个数

那么此时就转换成了

dp[i][j] = Math.max(dp[i][j],dp[i-x][j-y]+1)

因为此时如果能放进去,也就是加了1个物品

3.初始化dp数组

此时dp[0][0] 很轻易就能知道是0,为了我们的递推公式能顺利的覆盖结果,其他的也初始化为0

4.注意dp数组的遍历顺序

和之前一样,先遍历物品,再遍历背包即可

5.打印dp数组排错

题目代码:

class Solution {
    public int findMaxForm(String[] strs, int m, int n) {
        //dp数组含义
        int[][] dp = new int[m+1][n+1];
        //初始化,全为0
        for(String s:strs){
            int x = 0,y = 0;
            for(char c:s.toCharArray()){
                if(c == '0'){
                    x++;
                }else{
                    y++;
                }
            }
            for(int i = m;i>=x;i--){
                for(int j = n;j>=y;j--){
                    dp[i][j] = Math.max(dp[i][j],dp[i-x][j-y]+1);
                }
                
            }
        }
        return dp[m][n];

    }
}

到了这里,关于代码随想录Day36 动态规划05 LeetCode T1049最后一块石头的重量II T494 目标和 T474 一和零的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 代码随想录 day38 第九章 动态规划part01

    ●  理论基础 ●  509. 斐波那契数 ●  70. 爬楼梯 ●  746. 使用最小花费爬楼梯 理论基础 解决动态规划必须要想清楚的点 dp数组以及下标的含义 递推公式 dp数组如何初始化 遍历顺序 打印数组 检查结果 关联 leetcode 509. 斐波那契数 思路 动规五部曲 dp数组以及下标的含义

    2024年04月17日
    浏览(31)
  • Day39 代码随想录(1刷) 动态规划 0-1背包

    题目描述 小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的空间,并且具有不同的价值。  小明的行李空间

    2024年04月23日
    浏览(37)
  • 【Day52】代码随想录之动态规划_打家劫舍

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

    2024年02月22日
    浏览(38)
  • 【代码随想录】刷题Day36

    435. 无重叠区间 先从小到大排序,其实本题依然是求出共同区域,只不过题目需要我们删除尽量少的区间。所以我们需要删除的一定是范围跨度大的并且跟其他有公共区间的区域。所以每次更新右边范围都需要考虑最小的范围。 1.if(intervals[i][0]end),说明有重复的区间,那么我

    2024年02月07日
    浏览(33)
  • 【Day42】代码随想录之动态规划0-1背包_416. 分割等和子集

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

    2024年02月20日
    浏览(42)
  • 【Day45】代码随想录之动态规划part7—爬楼梯(进阶)、零钱兑换、完全平方数

    今天又是补打卡的一天,开冲!!! 今日任务: 70.爬楼梯(进阶) 322.零钱兑换 279.完全平方数 这道题之前做过一次,但是可以采用完全背包的问题来分析一遍。 卡玛网题目:【57.爬楼梯】 这个题目其实是更难了一点,因为前面的题目都是每次要不爬1阶楼梯,要不爬2阶楼

    2024年03月25日
    浏览(40)
  • 我在代码随想录|写代码Day33 | 动态规划| 路径问题| 62.不同路径,63. 不同路径 II,343. 整数拆分

    🔥博客介绍`: 27dCnc 🎥系列专栏: 数据结构与算法 算法入门 C++项目 🎥 当前专栏: 算法入门 专题 : 数据结构帮助小白快速入门算法 👍👍👍👍👍👍👍👍👍👍👍👍 ☆*: .。. o(≧▽≦)o .。.:*☆ ❤️感谢大家点赞👍收藏⭐评论✍️ 今日学习打卡 代码随想录 - 动态规划

    2024年03月11日
    浏览(40)
  • 【Day53】代码随想录之动态规划part10——买卖股票的最佳时机、买卖股票的最佳时机II

    昨天已经把打家劫舍的问题解决了,最后一个题目涉及到树形dp比较难(等到二刷的时候再重点看下),今天的任务是解决股票问题。 今日任务: 121.买卖股票的最佳时机 122.买卖股票的最佳时机II Leetcode题目:【121.买卖股票的最佳时机】 因为此题中买卖股票只能买卖一次。

    2024年03月15日
    浏览(81)
  • 【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日
    浏览(39)
  • 代码随想录Day32 动态规划01 LeetCodeT509 斐波那契数列 T70 爬楼梯 T746 爬楼梯的最小消耗

    动态规划首先可以解决的问题有背包问题,打家劫舍问题,股票问题,子序列问题等,主要是将一个大的问题切分成多个重叠的子问题,所以动态规划一定是上一个状态递推过来的,有一个重要的 状态转移方程, 但是这也并不是解题的全部,我们将动态规划的题目基本分为五步来完成

    2024年02月06日
    浏览(44)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包