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

乐器产品主要在什么网站做推广做网站常用软件

乐器产品主要在什么网站做推广,做网站常用软件,wordpress 文章视频,个人做电商网站一、实战 1049最后一块石头的重量 II 1049. 最后一块石头的重量 II - 力扣(LeetCode) 思路:本题实质上和上一题 416. 分割等和子集类似,尽量让石头分成重量相同的两堆(尽可能相同),相撞之后剩下…

一、实战

1049最后一块石头的重量 II

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

思路:本题实质上和上一题 416. 分割等和子集类似,尽量让石头分成重量相同的两堆(尽可能相同),相撞之后剩下的石头就是最小的。一堆的石头重量是sum,那么我们就尽可能拼成 重量为 sum / 2 的石头堆。 这样剩下的石头堆也是 尽可能接近 sum/2 的重量。 那么此时问题就是有一堆石头,每个石头都有自己的重量,是否可以 装满 最大重量为 sum / 2的背包。转化成01背包问题

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

dp[j]表示容量为j的背包,最多可以背最大重量为dp[j]。

2. 确定递推公式

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

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

3. dp数组如何初始化

既然 dp[j]中的j表示容量,那么最大容量(重量)是多少呢,就是所有石头的重量和。提示中给出1 <= stones.length <= 30,1 <= stones[i] <= 1000,所以最大重量就是30 * 1000 。而要求的target其实只是最大重量的一半,所以dp数组开到15000大小就可以了。考虑到边界值,就取用15001

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

4. 确定遍历顺序

在动态规划:关于01背包问题,你该了解这些!(滚动数组) (opens new window)中就已经说明:如果使用一维dp数组,物品遍历的for循环放在外层,遍历背包的for循环放在内层,且内层for循环倒序遍历!具体可以见之前几篇,总之就是使用一维滚动数组的时候,外层物品内层背包固定。

5. 举例推导dp数组

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

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

最后dp[target]里是容量为target的背包所能背的最大重量。那么分成两堆石头,一堆石头的总重量是dp[target],另一堆就是sum - dp[target]。在计算target的时候,target = sum / 2 因为是向下取整,所以sum - dp[target] 一定是大于等于dp[target]的。那么相撞之后剩下的最小石头重量就是 (sum - dp[target]) - dp[target]。

package org.example.DP;public class lastStoneWeightII1049 {public int lastStoneWeightII(int[] stones) {int sum = 0;//计算数组中所有相加总和for (int i : stones) {sum += i;}int target = sum / 2;//最终目标值int[] dp = new int[target + 1];//其实可以直接15000+1,但是用target能节省更多的空间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-2*dp[target];}
}

494目标和

494. 目标和 - 力扣(LeetCode)

本题要如何使表达式结果为target,将数组分为两个集合,正数集合left,减数集合right,一定有 left组合 - right组合 = target。left + right = sum,而sum是固定的。right = sum - left

left - (sum - left) = target 推导出 left = (target + sum)/2 。target是固定的,sum是固定的,left就可以求出来。此时问题就是在集合nums中找出和为left的组合。如果(target + sum)/2不是偶数,也就是(target + sum) % 2为1的情况,则找不到答案。

1. dp数组含义。

这里dp[j]表示容量为j的背包,装满的方法最大有几种。注意不是最大价值,是方法的数量!!

2. 确定递推公式

二维DP数组递推公式: dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i]];(dp[i][j]:使用 下标为[0, i]的nums[i]能够凑满j(包括j)这么大容量的包,有dp[i][j]种方法。)

去掉维度i 之后,递推公式:dp[j] = dp[j] + dp[j - nums[i]] ,即:dp[j] += dp[j - nums[i]]

这个公式在后面在讲解背包解决排列组合问题的时候还会用到!

3. dp数组如何初始化

这里dp[0]初始为1 ,即装满背包为0的方法有一种,放0件物品。如果设置为0,在递推公式累加的情况下一直为0,再结合具体情况,所以初始为1。

#4. 确定遍历顺序

在动态规划:关于01背包问题,你该了解这些!(滚动数组) (opens new window)中系统讲过对于01背包问题一维dp的遍历。遍历物品放在外循环,遍历背包在内循环,且内循环倒序(为了保证物品只使用一次)。

#5. 举例推导dp数组

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

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

dp数组状态变化如下:

拓展
关于一维dp数组的递推公式解释,也可以从以下维度来理解。(但还是从二维DP数组到一维DP数组这样更容易理解一些)

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

例如:dp[j],j 为5,

已经有一个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]有多少方法呢,也就是把 所有的 dp[j - nums[i]] 累加起来。

所以求组合类问题的公式,都是类似这种:

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

package org.example.DP;public class findTargetSumWays494 {public int findTargetSumWays(int[] nums, int target) {int sum = 0;//计算数组中所有相加总和for (int i : nums) {sum += i;}//如果target的绝对值大于sum,那么是没有方案的if (Math.abs(target) > sum) return 0;//如果(target+sum)除以2的余数不为0,也是没有方案的if ((target + sum) % 2 == 1) return 0;int bag=(target + sum)/2;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一和零

474. 一和零 - 力扣(LeetCode)

本题并不是多重背包,再来看一下这个图,捋清几种背包的关系。多重背包是每个物品,数量不同的情况。本题中strs 数组里的元素就是物品,每个物品都是一个!而m 和 n相当于是一个背包,两个维度的背包。理解成多重背包主要是把m和n混淆为物品了,感觉这是不同数量的物品,所以以为是多重背包。但本题其实是01背包问题!只不过这个背包有两个维度,一个是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);

此时大家可以回想一下01背包的递推公式:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);对比一下就会发现,字符串的zeroNum和oneNum相当于物品的重量(weight[i]),字符串本身的个数相当于物品的价值(value[i])。

这就是一个典型的01背包! 只不过物品的重量有了两个维度而已。

3.dp数组如何初始化

在动态规划:关于01背包问题,你该了解这些!(滚动数组) (opens new window)中已经讲解了,01背包的dp数组初始化为0就可以。因为物品价值不会是负数,初始为0,保证递推的时候dp[i][j]不会被初始值覆盖。

4.确定遍历顺序

在动态规划:关于01背包问题,你该了解这些!(滚动数组) (opens new window)中,我们讲到了01背包为什么一定是外层for循环遍历物品,内层for循环遍历背包容量且从后向前遍历!那么本题也是,物品就是strs里的字符串,背包容量就是题目描述中的m和n。

package org.example.DP;public class findMaxForm474 {public int findMaxForm(String[] strs, int m, int n) {//dp[i][j]表示i个0和j个1时的最大子集,也就是最大个数int[][] dp = new int[m + 1][n + 1];int oneNum, zeroNum;for (String str : strs) {oneNum = 0;zeroNum = 0;//统计每个中0和1的个数for (char ch : str.toCharArray()) {if (ch == '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.dtcms.com/a/521984.html

相关文章:

  • 淄博张店做网站的公司广州网站建设外贸
  • 深圳网站建设制作设计公司大学生创业50个小案例
  • 网站用户注册怎么做wordpress模板打开慢
  • 宝塔织梦网站建设免费网店代运营
  • 模板做网站影响seo泰安建设厅网站
  • 天津企业模板建站嘉兴互联网公司
  • 云服务器能否虚拟多个ip,一个云服务器怎么弄多个ip?
  • 创建一个网站 站点根文件夹为百度ai智能搜索引擎
  • S7-200 SMART CPU通信全解析:工业自动化的无缝连接之道
  • 从化网站制作互联网公司十大排名
  • 平原做网站看上去高端的网站
  • 已经有了网站怎么做推广wordpress系统
  • qq头像网站源码花店网站建设课程设计
  • 外贸网站设计师网站在百度的标头不对
  • 做淘宝素材网站哪个好用英雄联盟手游小程序被投诉
  • 正能量晚上看的网站2021自动app优化
  • C++仿muduo库高并发服务器项目:Socket模块
  • 湖南网站优化上海网站设计
  • 电子商务网站的功能有哪些哪个网站做团购要求低点
  • 淄博网站定制网站制作出租
  • 做家具的企业网站wordpress搭建方案
  • 苏州网站建设专家郑州网站建设技术支持
  • STM32学习和实践笔记(43):CAN通信实验(1)
  • 企业网站模板 优帮云百度搜索排名购买
  • 编程项目实例网站61源码网
  • 做壁纸网站好百度文库账号登录入口
  • UniVLA训练思路
  • 教育培训网站案例深圳网站建设 利科技
  • 网站2级目录怎么做个人网站首页内容
  • 禁忌网站wordpress 分类 标题