代码随想录-算法训练营day42(动态规划05:最后一块石头的重量2,目标和,一和零)

bash 复制代码
第九章 动态规划 part05
 
● 1049. 最后一块石头的重量 II 
● 494. 目标和 
● 474.一和零  
 
 详细布置 
 
 1049. 最后一块石头的重量 II 
 
本题就和 昨天的 416. 分割等和子集 很像了,可以尝试先自己思考做一做。 
视频讲解:https://www.bilibili.com/video/BV14M411C7oV 
https://programmercarl.com/1049.%E6%9C%80%E5%90%8E%E4%B8%80%E5%9D%97%E7%9F%B3%E5%A4%B4%E7%9A%84%E9%87%8D%E9%87%8FII.html  
 
 494. 目标和 
大家重点理解 递推公式:dp[j] += dp[j - nums[i]],这个公式后面的提问 我们还会用到。  
视频讲解:https://www.bilibili.com/video/BV1o8411j73x
https://programmercarl.com/0494.%E7%9B%AE%E6%A0%87%E5%92%8C.html  
 
 
 474.一和零  
通过这道题目,大家先粗略了解, 01背包,完全背包,多重背包的区别,不过不用细扣,因为后面 对于 完全背包,多重背包 还有单独讲解。
视频讲解:https://www.bilibili.com/video/BV1rW4y1x7ZQ 
https://programmercarl.com/0474.%E4%B8%80%E5%92%8C%E9%9B%B6.html

day42

最后一块石头的重量2

复制代码
 //把石头分成重量相近的两堆,然后一边取一个放进去磨,左边石头磨完了再从左边取一个放进去和右边磨过的石头一起磨,这样最后剩下的时候头就是abs(左堆重量- 右堆重量)
 class Solution {
     public int lastStoneWeightII(int[] stones) {
         int sum = 0;
         for( int num : stones){
             sum += num;
         }
         int target = sum >> 1 ;
         int[] dp = new int[target + 1];
         //初始化
         //for(int i = stones[0]; i <= target; i++){//这里i = target也需要初始化
         //    dp[i] = stones[0];
         //}
         //for( int i = 1; i < stones.length ; i++){
         for( int i = 0; i < stones.length ; i++){//对一维来说,第一行的初始化可以放进循环,因为不涉及dp[i - 1][j],所以i可以为0
             for( int j = target; j >= stones[i] ; j--){
                 dp[j] = Math.max( dp[j], dp[j - stones[i]] + stones[i]);
             }
         }
         return sum - 2 * dp[target];
     }
 }

目标和

dp[i][j]表示用0~i号元素装满容量j,的方法,的个数

复制代码
 //为了理解一维数组,在idea中的调试代码
 class demo02 {
     public static void main(String[] args) {
         int[] nums = {0,0,0};
         int target = 0;
         findTargetSumWays(nums,target);
     }
     public static int findTargetSumWays(int[] nums, int target) {
         //分成两组left和right,left - right = target即可,又因为left+right = sum,消去right,left = (sum + target)/2
         //dp[i][j]表示从物品0到i去选,能组成容量j的 方法 有多少种
         //不放物品i和放物品i两种情况推出来:dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i]](也就是留出放j的空间去)
         int sum = 0;
         for(int i : nums){
             sum += i;
         }
         if((sum + target ) % 2 != 0) return 0;
         if( sum < Math.abs(target) ) return 0;
         int bagweight = sum + target >> 1;
         int[][] dp = new int[nums.length][bagweight + 1];
         //初始化
         //第一行,只有nums[0] == j的时候,以及j == 0的时候,为1,其他都为0
         //我们把dp[0][0]留给列去初始化,因为nums[0]是0的时候dp[0][0]是2
         //对于一维数组来说,他的第一行初始化可以自己赋值,dp[0][0]是1还是2,也可以直接交给for里面i=0,但是初始化之前依然要把dp[0]赋值为0
         //这是因为相当于是从[1,0,0,0]去初始化的i = 0这一行,如果第一个nums[0]==0,i=0那一行就是[2,0,0,0]
         //一维数组可以避免非常麻烦的初始化
         if(nums[0] <= bagweight) dp[0][nums[0]] = 1;//记得数组下标都需要判断一下
         //第一列,什么都不放这一种方法,或者数组里面有0
         //for(int i = 0; i < nums.length; i++){//这个初始化忽略了数组中可能有0的情况
         //    dp[i][0] = 1;
         //}
         int numZeros = 0;
         for(int i = 0; i < nums.length; i++) {
             if(nums[i] == 0) {
                 numZeros++;
             }
             dp[i][0] = (int) Math.pow(2, numZeros);
         }
         //for(int i = 0; i < nums.length; i++){//这个初始化忽略了数组中可能有0的情况
         //    dp[i][0] = 1;
         //}
         for(int i = 1; i < nums.length ; i++) {
             for (int j = 1; j <= bagweight; j++) {
                 if (j < nums[i]) dp[i][j] = dp[i - 1][j];
                 else dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i]];
             }
         }
         printall(dp);
         return dp[nums.length - 1][bagweight];
     }
     public static void printall(int[][] dp){
         int numslength = dp.length;
         int weight = dp[0].length;
         for(int i = 0; i < numslength ; i++) {
             for (int j = 0; j < weight; j++) {
                 System.out.print(dp[i][j]);
                 System.out.print(" ");
             }
             System.out.println();
         }
     }
 }

一和零

复制代码
 class Solution {
     public int findMaxForm(String[] strs, int m, int n) {
         //背包有两个容量mn
         int[][] dp = new int[m+1][n+1];
         //初始化都为0
         //先遍历物品再遍历背包
         for( String str : strs){
             int x = 0;
             int y = 0;
             for(char ch : str.toCharArray()){
                 if(ch == '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];
     }
 }

感谢大佬分享:

代码随想录-算法训练营day42【动态规划05:最后一块石头的重量II、目标和、一和零】-CSDN博客

相关推荐
我是一只来自东方的鸭.6 分钟前
1. K11504 天平[Not so Mobile,UVa839]
数据结构·b树·算法
weixin_5375904518 分钟前
《Java编程入门官方教程》第八章练习答案
java·开发语言·servlet
星语心愿.43 分钟前
D4——贪心练习
c++·算法·贪心算法
光头man43 分钟前
【八大排序(二)】希尔排序
算法·排序算法
CodeClimb44 分钟前
【华为OD-E卷-最左侧冗余覆盖子串 100分(python、java、c++、js、c)】
java·python·华为od
武昌库里写JAVA1 小时前
使用React Strict DOM改善React生态系统
数据结构·vue.js·spring boot·算法·课程设计
创意锦囊1 小时前
随时随地编码,高效算法学习工具—E时代IDE
ide·学习·算法
Q_19284999061 小时前
基于Spring Boot的大学就业信息管理系统
java·spring boot·后端
stm 学习ing1 小时前
HDLBits训练3
c语言·经验分享·笔记·算法·fpga·eda·verilog hdl