当前位置: 首页 > news >正文

新市网站建设中国工厂货源求购网

新市网站建设,中国工厂货源求购网,广州网站建设开发公司,安徽网页设计培训算法训练营 day46 动态规划 最后一块石头的重量 II 目标和 一和零 最后一块石头的重量 II 1049. 最后一块石头的重量 II - 力扣(LeetCode) 有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xf…

算法训练营 day46 动态规划 最后一块石头的重量 II 目标和 一和零

最后一块石头的重量 II

1049. 最后一块石头的重量 II - 力扣(LeetCode)

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

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

如果 x == y,那么两块石头都会被完全粉碎;
如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。
最后,最多只会剩下一块 石头。返回此石头 最小的可能重量 。如果没有石头剩下,就返回 0。

本题其实就是尽量让石头分成重量相同的两堆,相撞之后剩下的石头最小,这样就化解成01背包问题了

是不是感觉和昨天讲解的416. 分割等和子集非常像了。

本题物品的重量为stones[i],物品的价值也为stones[i]。

对应着01背包里的物品重量weight[i]和 物品价值value[i]。

接下来进行动规五步曲:

  1. 确定dp数组以及下标的含义

dp[j]表示容量(这里说容量更形象,其实就是重量)为j的背包,最多可以背最大重量为dp[j]

  1. 确定递推公式

01背包的递推公式为:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

本题则是:dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);

  1. dp数组如何初始化

因为重量都不会是负数,所以dp[j]都初始化为0就可以了,这样在递归公式dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);中dp[j]才不会初始值所覆盖。

  1. 确定遍历顺序

如果使用一维dp数组,物品遍历的for循环放在外层,遍历背包的for循环放在内层,且内层for循环倒序遍历!

  1. 举例推导dp数组

举例,输入:[2,4,1,1],此时target = (2 + 4 + 1 + 1)/2 = 4 ,dp数组状态图如下:

在这里插入图片描述

一维dp数组

class Solution {public  int lastStoneWeightII(int[] stones) {int sum = 0;for (int a : stones) {sum += a;}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--) {if (j < stones[i]) {dp[j] = dp[j];} else {dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]);}}}return (sum - dp[target]) - dp[target];}
}

二维dp数组

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

目标和

494. 目标和 - 力扣(LeetCode)

给你一个整数数组 nums 和一个整数 target 。

向数组中的每个整数前添加 ‘+’ 或 ‘-’ ,然后串联起所有整数,可以构造一个 表达式 :

例如,nums = [2, 1] ,可以在 2 之前添加 ‘+’ ,在 1 之前添加 ‘-’ ,然后串联起来得到表达式 “+2-1” 。
返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

假设加法的总和为x,那么减法对应的总和就是sum - x。

所以我们要求的是 x - (sum - x) = target

x = (target + sum) / 2

此时问题就转化为,装满容量为x的背包,有几种方法

这里的x,就是bagSize,也就是我们后面要求的背包容量。

大家看到(target + sum) / 2 应该担心计算的过程中向下取整有没有影响。

这么担心就对了,例如sum 是5,S是2的话其实就是无解的

  1. 确定dp数组以及下标的含义

    dp[j] 表示:填满j(包括j)这么大容积的包,有dp[j]种方法

    其实也可以使用二维dp数组来求解本题,dp[i][j]:使用 下标为[0, i]的nums[i]能够凑满j(包括j)这么大容量的包,有dp[i][j]种方法。

  2. 确定递推公式

    只要搞到nums[i],凑成dp[j]就有dp[j - nums[i]] 种方法。

    凑整dp[5]有多少方法呢,也就是把 所有的 dp[j - nums[i]] 累加起来。

  3. dp数组如何初始化

    从递推公式可以看出,在初始化的时候dp[0] 一定要初始化为1,因为dp[0]是在公式中一切递推结果的起源,如果dp[0]是0的话,递推结果将都是0。

  4. 确定遍历顺序

    对于01背包问题一维dp的遍历,nums放在外循环,target在内循环,且内循环倒序。

  5. 举例推导dp数组

    输入:nums: [1, 1, 1, 1, 1], S: 3

    bagSize = (S + sum) / 2 = (3 + 5) / 2 = 4

    dp数组状态变化如下:

    在这里插入图片描述

一维dp数组

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

二维dp数组

    public static int findTargetSumWays(int[] nums, int target) {int sum = 0;for (int num : nums) {sum += num;}int S = (sum + target) / 2;if (sum < Math.abs(target)) return 0;if ((target + sum) % 2 != 0) return 0;int[][] dp = new int[nums.length + 1][S + 1];dp[0][0] = 1;for (int i = 1; i <= nums.length; i++) {for (int j = 0; j <= S; j++) {if (j < nums[i - 1]) {dp[i][j] = dp[i - 1][j];} else {dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i - 1]];}}}return dp[nums.length][S];}

一和零

474. 一和零 - 力扣(LeetCode)

给你一个二进制字符串数组 strs 和两个整数 m 和 n 。

请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。

如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。

本题中strs 数组里的元素就是物品,每个物品都是一个!

而m 和 n相当于是一个背包,两个维度的背包

  1. 确定dp数组(dp table)以及下标的含义

    dp[i][j]:最多有i个0和j个1的strs的最大子集的大小为dp[i][j]

  2. 确定递推公式

    dp[i][j] 可以由前一个strs里的字符串推导出来,strs里的字符串有zeroNum个0,oneNum个1。

    dp[i][j] 就可以是 dp[i - zeroNum][j - oneNum] + 1

    然后我们在遍历的过程中,取dp[i][j]的最大值。

    所以递推公式:dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);

  3. dp数组如何初始化

    因为物品价值不会是负数,初始为0,保证递推的时候dp[i][j]不会被初始值覆盖。

  4. 确定遍历顺序

    物品就是strs里的字符串,背包容量就是题目描述中的m和n。

  5. 举例推导dp数组

    以输入:[“10”,“0001”,“111001”,“1”,“0”],m = 3,n = 3为例

    最后dp数组的状态如下所示:

在这里插入图片描述

    public int findMaxForm(String[] strs, int m, int n) {int[][] dp = new int[m + 1][n + 1];for (String str : strs) {int oneNum = 0, zeroNum = 0;for (char c : str.toCharArray()) {if (c == '0') zeroNum++;else oneNum++;}for (int i = m; i >= zeroNum; i--) {for (int j = n; j >= oneNum; j--) {dp[i][j] = Math.max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);}}}return dp[m][n];}
http://www.15wanjia.com/news/164423.html

相关文章:

  • 网站排名优化是怎么做的seo排名软件价格
  • 高端网站建设公司排行郑州网站关键词优化外包
  • 装修建材网站模板哪些网站的做的好看
  • 东莞南城网站制作中文外贸网站建设
  • 网站设计的公司报价linux wordpress 下载文件
  • 陕西建筑工程网百度搜索优化怎么做
  • 网站被攻击会影响收录么扬中新闻中心
  • 网站原型图设计软件网站开发文档下载
  • 建立网站对吗17. 整个网站建设中的关键是
  • 常州建设银行网站关于美食的网页模板
  • html做的网站图片横着摆放自己做交易网站吗
  • 注册查询网站便宜点的网站空间
  • 做产品网站桂林市临桂区城乡建设局网站
  • 深圳网站定制开发网站选择理由描述
  • 专业做网站的企业涞水县建设局网站
  • 旅游网站开发的流程图seo优化方案怎么写
  • 网站服务器失去响应怎么解决单位网站建设存在问题情况汇报
  • 南宁网站建设服务商天元建设集团有限公司鲁班奖
  • 运营实力 网站建设培训机构网站设计
  • 重庆seo研究中心简述seo和sem的区别
  • mvc 网站模板千锋教育培训多少钱费用
  • 如何免费自己做个网站浙江网站备案
  • 网站备案 不关站临沂市建设官方网站
  • 平台网站开发是什么意思简述什么是seo
  • 南宁做网站的公司有哪些网站建设方案书人员资金安排
  • 滁州网站定制ppt模板免费下载百度网盘
  • 做网站用什么技术网站建设如何制作教程
  • 外国人做的古文字网站网站降权怎么救
  • 图片网站怎么做排名《网页设计与网站建设》A卷答案
  • 金融网站建设网设计者联盟官网