滑动窗口系列4-Leetcode322题零钱兑换-限制张数-暴力递归到动态规划再到滑动窗口
这个题目是Leecode322的变种,322原题如下:

我们这里的变化是把硬币变成可以重复的,并且只有coins数组中给出的这么多的金币,也就是说有数量限制:
package dataStructure.leecode.practice;import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;public class CoinsChange {public static int coinChange(int[] coins, int amount) {if(amount == 0) return 0;int nums = process(coins, 0, amount);return nums == Integer.MAX_VALUE? -1 : nums;}/*** 最傻的递归* @param coins* @param curIndex* @param restAmount* @return*/public static int process(int[] coins, int curIndex, int restAmount) {if(restAmount == 0) return 0;if(curIndex == coins.length) return Integer.MAX_VALUE;//两种可能性:用当前位置的数字或者不用当前位置的数字int p1 = process(coins, curIndex + 1, restAmount);int ans = p1;int p2 = process(coins, curIndex + 1, restAmount - coins[curIndex]);if(p2 != Integer.MAX_VALUE) {ans = Math.min(ans, p2 + 1);}return ans;}/*** 最傻的递归改的动态规划* @param coins* @return*/public static int coinChangeDp(int[] coins, int amount) {int N = coins.length;int[][] dp = new int[N + 1][amount + 1];for(int j = 1; j <= amount; j++) {dp[N][j] = Integer.MAX_VALUE;}for(int curIndex = N - 1; curIndex >= 0; curIndex --) {for(int restAmount = 0; restAmount <= amount; restAmount ++) {//两种可能性:用当前位置的数字或者不用当前位置的数字int p1 = dp[curIndex + 1][restAmount];int ans = p1;if(restAmount - coins[curIndex] >= 0) {int p2 = dp[curIndex + 1][restAmount - coins[curIndex]];if(p2 != Integer.MAX_VALUE) {ans = Math.min(ans, p2 + 1);}}dp[curIndex][restAmount] = ans;}}return dp[0][amount];}public static int coinChange2(int[] coins, int amount) {if(amount == 0) return 0;CoinsInfo coinsInfo = getCoinsInfo(coins);int nums = process2(coinsInfo.values, coinsInfo.nums, 0, amount);return nums == Integer.MAX_VALUE? -1 : nums;}public static CoinsInfo getCoinsInfo(int[] coins) {//使用HashMap做频次的统计HashMap<Integer, Integer> count = new HashMap<>();//Arrays.sort(coins);//遍历coins的每个硬币并进行统计for (int coin : coins) {if(count.containsKey(coin)) {count.put(coin,count.get(coin) + 1);} else {count.put(coin, 1);}}//初始化values和nums数组,分别表示金额和数量,二者长度相等且一一对应int[] values = new int[count.size()];int[] nums = new int[count.size()];//根据count进行填充,从0下标开始填充int curIndex = 0;for (Integer value : count.keySet()) {//当前下标的value和num设置values[curIndex] = value;//这里要++,这样下次循环就可以进行下一个面值的统计了nums[curIndex ++] = count.get(value);}return new CoinsInfo(values, nums);}/*** 改进的递归-把coins按照面值进行分类,如果有很多重复的可以大大提高效率* @param values* @param nums* @param curIndex* @param restAmount* @return*/public static int process2(int[] values, int[] nums, int curIndex, int restAmount) {if(restAmount == 0) return 0;if(curIndex == values.length) return Integer.MAX_VALUE;//当前面值的钱可以用0个到nums[curIndex]个int ans = process2(values, nums, curIndex + 1, restAmount);for(int num = 1; num <= nums[curIndex]; num ++) {int nextMin = process2(values, nums, curIndex + 1, restAmount - num *values[curIndex]);if(nextMin != Integer.MAX_VALUE) {ans = Math.min(ans, nextMin) + num;}}return ans;}public static int coinChangeDp2(int[] coins, int amount) {if(amount == 0) return 0;CoinsInfo coinsInfo = getCoinsInfo(coins);int[] values = coinsInfo.values;int[] nums = coinsInfo.nums;int N = values.length;//动态规划数组int[][] dp = new int[N + 1][amount + 1];/*if(restAmount == 0) return 0;if(curIndex == values.length) return Integer.MAX_VALUE;*///根据递归中的上面两个if初始化动态规划数组, int默认是0所以第一个if忽略for(int j = 1; j <= amount; j++) {dp[N][j] = Integer.MAX_VALUE;}//对于普遍位置进行赋值for(int curIndex = N - 1; curIndex >= 0; curIndex --) {for(int restAmount = 0; restAmount <= amount; restAmount ++) {//当前面值的钱可以用0个到nums[curIndex]个int ans = dp[curIndex + 1][restAmount];for(int num = 1; num <= nums[curIndex]; num ++) {int nextMin = dp[curIndex + 1][restAmount - num *values[curIndex]];if(nextMin != Integer.MAX_VALUE) {ans = Math.min(ans, nextMin) + num;}}//斜率优化的相关分析,假设values数组为[1,2,3,5] nums为[4,2,2,1], amount = 15;//那我们推算dp[1][8] = dp[2][8] dp[2][6] + 1 dp[2][4] + 2中取最小值//而dp[1][6] = dp[2][6] dp[2][4] + 1 dp[2][2] + 2中的最小值//此时的dp[1][8]并不能根据dp[1][6]和dp[2][8]计算出,因为dp[1][6]用到的dp[2][2]+2在dp[1][8]中并没有,而这个可能就是最小值}}int result = dp[0] [amount];return result == Integer.MAX_VALUE? -1 : result;}public static int coinChangeSlideWindow(int[] coins, int aim) {if(aim == 0) return 0;CoinsInfo coinsInfo = getCoinsInfo(coins);int[] values = coinsInfo.values;int[] nums = coinsInfo.nums;int N = values.length;//动态规划数组int[][] dp = new int[N + 1][aim + 1];/*if(restAmount == 0) return 0;if(curIndex == values.length) return Integer.MAX_VALUE;*///根据递归中的上面两个if初始化动态规划数组, int默认是0所以第一个if忽略for(int j = 1; j <= aim; j++) {dp[N][j] = Integer.MAX_VALUE;}//对于普遍位置进行赋值for(int curIndex = N - 1; curIndex >= 0; curIndex --) {//使用窗口内最小值的更新结构,对于每个面值的货币尝试的方位是0~(目标金额和货币金额达的最小值-1)//比如如果面值是30,而目标值是100,那我们进行以下的尝试:(0 30 60 90) (1 31, 61, 91) ...(29, 59, 89)//而对于面值100,目标值30,我们进行:(0) (1)...(29)这些尝试//mod代表我们当前准备尝试多少组,例如上面的面值是30,而目标值是100,我们mod就从0到29,一共30组for(int mod = 0; mod < Math.min(aim+1, coins[curIndex]); mod ++) {//创建一个最小值窗口,放的是当前的金额LinkedList<Integer> window = new LinkedList<>();//mod是当前组的第一个位置,先进去,暂时是窗口最小值window.add(mod);//先把dp[curIndex][mod]的初始值设置为dp[curIndex + 1][mod]dp[curIndex][mod] = dp[curIndex + 1][mod];//在小于目标金额的情况下,每次加当前面值,类似0 30 60 90,不超过目标金额for(int curAmount = mod + coins[curIndex]; curAmount <= aim; curAmount += coins[curIndex]) {//如果窗口不为空且窗口最后的数是Integer的最大值或者最后的值+补偿金额大于当前的数量(下一行的dp值)while(!window.isEmpty() && (dp[curIndex+1][window.peekLast()] == Integer.MAX_VALUE || window.peekLast() + composite(window.peekLast(), curAmount, coins[curIndex]) >= dp[curIndex + 1][curAmount])) {window.pollLast();}//把当前金额(dp里的列)window.addLast(curAmount);//当前钱数-货币金额*货币数量刚好是可用的,如果再加一个就不行了,计算当前值或者计算下一个值的时候就都不能用了int overdue = curAmount - coins[curIndex] * (nums[curIndex] + 1);if(window.peekFirst() == overdue) {window.pollFirst();}dp[curIndex][curAmount] = dp[curIndex + 1][window.peekFirst()] + composite(window.peekFirst(), curAmount, coins[curIndex]);}//斜率优化的相关分析,假设values数组为[1,2,3,5] nums为[4,2,2,1], amount = 15;//那我们推算dp[1][8] = dp[2][8] dp[2][6] + 1 dp[2][4] + 2中取最小值//而dp[1][6] = dp[2][6] dp[2][4] + 1 dp[2][2] + 2中的最小值//此时的dp[1][8]并不能根据dp[1][6]和dp[2][8]计算出,因为dp[1][6]用到的dp[2][2]+2在dp[1][8]中并没有,而这个可能就是最小值}}int result = dp[0] [aim];return result == Integer.MAX_VALUE? -1 : result;}private static int composite(int preAmount, int curAmount, int coinAmount) {return (curAmount - preAmount)/ coinAmount;}public static void main(String[] args) {int[] coins = {2,5,3,2,5,2};int amount = 15;int nums = coinChange(coins, amount);System.out.println(nums);int numsDp = coinChangeDp(coins, amount);System.out.println(numsDp);int nums2 = coinChange2(coins, amount);System.out.println(nums2);int numsDp2 = coinChange2(coins, amount);System.out.println(numsDp2);int numsWindow = coinChangeSlideWindow(coins, amount);System.out.println(numsWindow);}
}class CoinsInfo {int[] values;int[] nums;public CoinsInfo(int[] values, int[] nums) {this.values = values;this.nums = nums;}
}
相关文章:
滑动窗口系列4-Leetcode322题零钱兑换-限制张数-暴力递归到动态规划再到滑动窗口
这个题目是Leecode322的变种,322原题如下: 我们这里的变化是把硬币变成可以重复的,并且只有coins数组中给出的这么多的金币,也就是说有数量限制: package dataStructure.leecode.practice;import java.util.Arrays; i…...
Nginx全局配置
一、修改启动进程数 worker_processes 1; #允许的启动工作进程数数量,和你真实的cpu数量有关 1 worker_processes auto; #如果设置为auto 就是你真实的cpu数量 ps axo pid,cmd,psr,ni|grep nginx #可以看到 nginx的 worker数量 二、日制分割 [rootyuji ~]#…...
VUE笔记(四)vue的组件
一、组件的介绍 1、组件的作用 整个项目都是由组件组成 可以让代码复用:相似结构代码可以做成一个组件,直接进行调用就可以使用,提高代码复用性 可以让代码具有可维护性(只要改一处,整个引用的部分全部都变…...
菜鸟教程《Python 3 教程》笔记
菜鸟教程《Python 3 教程》笔记 0 写在前面1 基本数据类型1.1 Number(数字)1.2 String(字符串)1.3 bool(布尔类型)1.4 List(列表)1.5 Tuple(元组)1.6 Set&…...
JAVA学习-愚见
JAVA学习-愚见 分享一下Java的学习路线,仅供参考【本人亲测,真实有效】 1、尽可能推荐较新的课程 2、大部分视频在B站上直接搜关键词就行【自学,B大的学生】 文章目录 JAVA学习-愚见前期准备Java基础课程练手项目 数据库JavaWeb前端基础 Vue…...
Watch数据监听详解
一、Vue2写法 1、watch使用的几种方法 1、通过 watch 监听 data 数据的变化,数据发生变化时,就会打印当前的值 watch: {data(val, value) {console.log(val)console.log(value)}} 2、通过 watch 监听 list 数据的变化,数据发生变化时&…...
UML建模以及几种类图的理解
文章目录 前言1.用例与用例图1.1 参与者1.2 用例之间的关系1.3 用例图1.4 用例的描述 2.交互图2.1 顺序图2.2 协作图 3.类图和对象图3.1 关联关系3.2 聚合和组合3.3 泛化关系3.4 依赖关系 4.状态图与活动图4.1 状态图4.2 活动图 5.构件图 前言 UML通过图形化的表示机制从多个侧…...
opencv进阶18-基于opencv 决策树导论
1. 什么是决策树? 决策树是最早的机器学习算法之一,起源于对人类某些决策过程 的模仿,属于监督学习算法。 决策树的优点是易于理解,有些决策树既可以做分类,也可以做回归。在排名前十的数据挖掘算法中有两种是决策树[1…...
13.4 目标检测锚框标注 非极大值抑制
锚框的形状计算公式 假设原图的高为H,宽为W 锚框形状详细公式推导 以每个像素为中心生成不同形状的锚框 # s是缩放比,ratio是宽高比 def multibox_prior(data, sizes, ratios):"""生成以每个像素为中心具有不同形状的锚框"""in_he…...
【论文笔记】最近看的时空数据挖掘综述整理8.27
Deep Learning for Spatio-Temporal Data Mining: A Survey 被引用次数:392 [Submitted on 11 Jun 2019 (v1), last revised 24 Jun 2019 (this version, v2)] 主要内容: 该论文是一篇关于深度学习在时空数据挖掘中的应用的综述。论文首先介绍了时空数…...
【大模型】基于 LlaMA2 的高 star 的 GitHub 开源项目汇总
【大模型】基于 LlaMA2 的高 star 的 GitHub 开源项目汇总 Llama2 简介开源项目汇总NO1. FlagAlpha/Llama2-ChineseNO2. hiyouga/LLaMA-Efficient-TuningNO3. yangjianxin1/FireflyNO4. LinkSoul-AI/Chinese-Llama-2-7bNO5. wenge-research/YaYiNO6. michael-wzhu/Chinese-LlaM…...
解决elementUI打包上线后icon图标偶尔乱码的问题
解决vue-elementUI打包后icon图标偶尔乱码的问题 一、背景二、现象三、原因四、处理方法方式1:使用css-unicode-loader方式2:升高 sass版本到1.39.0方式3:替换element-ui的样式文件方式4:更换打包压缩方式知识扩展:方式…...
yolov3加上迁移学习和适度的数据增强形成的网络应用在输电线异物检测
Neural Detection of Foreign Objects for Transmission Lines in Power Systems Abstract. 输电线路为电能从一个地方输送到另一个地方提供了一条路径,确保输电线路的正常运行是向城市和企业供电的先决条件。主要威胁来自外来物,可能导致电力传输中断。…...
香橙派OrangePi zero H2+ 驱动移远EC200A
1 系统内核: Linux orangepizero 5.4.65-sunxi #2.2.2 SMP Tue Aug 15 17:45:28 CST 2023 armv7l armv7l armv7l GNU/Linux 1.1 下载内核头安装 下载:orangepi800 内核头rk3399链接https://download.csdn.net/download/weixin_37613240/87635781 1.1.1…...
写一个java中如何用JSch来连接sftp的类并做测试?(亲测)
当使用JSch连接SFTP服务器的类,并进行测试时,可以按照以下步骤操作: 添加JSch库的依赖项。在你的项目中添加JSch库的Maven依赖项(如前面所述)或下载JAR文件并将其包含在项目中。 <dependency> <groupId&…...
【沐风老师】如何在3dMax中将3D物体转化为样条线构成的对象?
在3dMax中如何把三维物体转化为由样条线构成的对象?通常这样的场景会出现在科研绘图或一些艺术创作当中,下面给大家详细讲解一种3dmax三维物体转样条线的方法。 第一部分:用粒子填充3D对象: 1.创建一个三维对象(本例…...
2023国赛数学建模思路 - 案例:随机森林
文章目录 1 什么是随机森林?2 随机深林构造流程3 随机森林的优缺点3.1 优点3.2 缺点 4 随机深林算法实现 建模资料 ## 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 什么是随机森林ÿ…...
wxpython:wx.html2 是好用的 WebView 组件
wxpython : wx.html2 是好用的 WebView 组件。 pip install wxpython4.2 wxPython-4.2.0-cp37-cp37m-win_amd64.whl (18.0 MB) Successfully installed wxpython-4.2.0 cd \Python37\Scripts wxdemo.exe 取得 wxPython-demo-4.2.0.tar.gz wxdocs.exe 取得 wxPython-docs-4.…...
《QT+PCL 第五章》点云特征-PFH
QT增加点云特征PFH 代码用法代码 #include <pcl/io/pcd_io.h> #include <pcl/features/normal_3d.h> #include <pcl/features/pfh.h>int main...
【分享】小型园区组网场景
小型园区组网图 在小型园区中,S2700&S3700通常部署在网络的接入层,S5700&S6700通常部署在网络的核心,出口路由器一般选用AR系列路由器。 接入交换机与核心交换机通过Eth-Trunk组网保证可靠性。 每个部门业务划分到一个VLAN中&#…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
