算法打卡day39|动态规划篇07| Leetcode 70. 爬楼梯(进阶版)、322. 零钱兑换、279.完全平方数

 算法题

Leetcode 70. 爬楼梯(进阶版)

题目:

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬至多m (1 <= m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

输入描述:输入共一行,包含两个正整数,分别表示n, m

输出描述:输出一个整数,表示爬到楼顶的方法数。

输入示例:3 2

输出示例:3

提示:

当 m = 2,n = 3 时,n = 3 这表示一共有三个台阶,m = 2 代表你每次可以爬一个台阶或者两个台阶。

此时你有三种方法可以爬到楼顶。

  • 1 阶 + 1 阶 + 1 阶段
  • 1 阶 + 2 阶
  • 2 阶 + 1 阶

 个人思路 

这道题是力扣70题的进阶版本,因为每阶都能重复使用,所以是一个完全背包问题,可以用动态规划方法解决。

解法
动态规划

这里的1阶,2阶,.... m阶就是物品,楼顶就是背包。每一阶可以重复使用,例如跳了1阶,还可以继续跳1阶。所以思路和昨天的题目组合总和四基本就是一道题了。

动规五部曲:

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

dp[i]:爬到有i个台阶的楼顶,有dp[i]种方法

2.确定递推公式

昨天的算法题,也是求装满背包有几种方法,这种递推公式一般都是dp[i] += dp[i - nums[j]];

而本题呢,dp[i]有几种来源,dp[i - 1],dp[i - 2],dp[i - 3] 等等,即:dp[i - j];

那么递推公式为:dp[i] += dp[i - j]

3.dp数组如何初始化

因为递归公式是 dp[i] += dp[i - j],所以dp[0] 一定为1,dp[0]是递归中一切数值的基础所在,如果dp[0]是0的话,其他数值都是0了。

下标非0的dp[i]初始化为0,因为dp[i]是靠dp[i-j]累计上来的,dp[i]本身为0这样才不会影响结果

4.确定遍历顺序

如果求组合数就是外层for循环遍历物品,内层for遍历背包

如果求排列数就是外层for遍历背包,内层for循环遍历物品

这是背包里求排列问题,即:1、2 步 和 2、1 步都是上三个台阶,但是这两种方法不一样!

所以需将target放在外循环,将nums放在内循环。每一步可以走多次,这是完全背包,内循环需要从前向后遍历。

5.举例来推导dp数组

import java.util.Scanner;
class climbStairs{public static void main(String [] args){Scanner sc = new Scanner(System.in);int m, n;while (sc.hasNextInt()) {n = sc.nextInt(); // 从键盘输入参数,中间用空格隔开m = sc.nextInt();// 求排列问题,先遍历背包再遍历物品int[] dp = new int[n + 1];dp[0] = 1;for (int j = 1; j <= n; j++) {for (int i = 1; i <= m; i++) {if (j - i >= 0) dp[j] += dp[j - i];}}System.out.println(dp[n]);}}
}

时间复杂度:O(n^2);(嵌套for循环)

空间复杂度:O( n);(存储一个长度为n+1的dp数组)


 Leetcode  322. 零钱兑换

题目链接:322. 零钱兑换

大佬视频讲解:零钱兑换视频讲解

个人思路

这道题的每种硬币的数量是无限的,典型的完全背包问题。

解法
动态规划

动规五部曲:

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

dp[j]:凑足总额为j所需钱币的最少个数为dp[j]

2.确定递推公式

凑足总额为j - coins[i]的最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] + 1就是dp[j](考虑coins[i])

所以dp[j] 要取所有 dp[j - coins[i]] + 1 中最小的

递推公式:dp[j] = min(dp[j - coins[i]] + 1, dp[j]);

3.dp数组如何初始化

首先凑足总金额为0所需钱币的个数一定是0,那么dp[0] = 0;

因为每次取最小的,所以dp[j]必须初始化为一个最大的数,否则就会在min(dp[j - coins[i]] + 1, dp[j])比较的过程中被初始值覆盖。所以下标非0的元素都是应该是最大值。

4.确定遍历顺序

本题是求钱币最小个数那么钱币有顺序和没有顺序都可以,都不影响钱币的最小个数

这里采用coins放在外循环,target在内循环的方式。本题钱币数量可以无限使用,那么是完全背包。所以遍历的内循环是正序

5.举例推导dp数组

以输入:coins = [1, 2, 5], amount = 5为例

class Solution {public int coinChange(int[] coins, int amount) {int max = Integer.MAX_VALUE;int[] dp = new int[amount + 1];for (int j = 0; j < dp.length; j++) { //初始化dp数组为最大值dp[j] = max;}dp[0] = 0; //当金额为0时需要的硬币数目为0for (int i = 0; i < coins.length; i++) {for (int j = coins[i]; j <= amount; j++) {//完全背包->正序遍历if (dp[j - coins[i]] != max) {//只有不是初始最大值时,该位才有选择的必要dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);//选择硬币数目最小的情况}}}return dp[amount] == max ? -1 : dp[amount];}
}

时间复杂度:O(n^2);(嵌套for循环)

空间复杂度:O( n);(存储一个长度为n+1的dp数组)


 Leetcode  279.完全平方数

题目链接:279.完全平方数

大佬视频讲解:完全平方数视频讲解

个人思路

还是完全背包问题,数字可以重复使用,和今天的前两天思路一样。

解法
动态规划

动规五部曲:

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

dp[j]:和为j的完全平方数的最少数量为dp[j]

2.确定递推公式

dp[j] 可以由dp[j - i * i]推出, dp[j - i * i] + 1 便可以凑成dp[j]。

选择最小的dp[j],所以递推公式:dp[j] = min(dp[j - i * i] + 1, dp[j]);

3.dp数组如何初始化

dp[0]表示 和为0的完全平方数的最小数量,那么dp[0]一定是0。

从递归公式dp[j] = min(dp[j - i * i] + 1, dp[j]);中可以看出每次dp[j]都要选最小的,所以非0下标的dp[j]一定要初始为最大值,这样dp[j]在递推的时候才不会被初始值覆盖

4.确定遍历顺序

这里只求最小个数,所以遍历顺序没有讲究。

5.举例推导dp数组

已输入n为5例,dp状态图如下:

class Solution {// 先遍历物品, 再遍历背包public int numSquares(int n) {int max = Integer.MAX_VALUE;int[] dp = new int[n + 1];Arrays.fill(dp, Integer.MAX_VALUE);//初始化dp[0] = 0; //当和为0时,组合的个数为0for (int i = 1; i * i <= n; i++) {//遍历物品for (int j = i * i; j <= n; j++) {// 遍历背包if (dp[j - i * i] != max) {dp[j] = Math.min(dp[j], dp[j - i * i] + 1);}}}return dp[n];}
}

时间复杂度:O(n^2);(嵌套for循环)

空间复杂度:O( n);(存储一个长度为n+1的dp数组)


 以上是个人的思考反思与总结,若只想根据系列题刷,参考卡哥的网址代码随想录算法官网

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/813533.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全新4.0版本圈子社交论坛系统 ,可打包小程序,于TP6+uni-app 全开源 可打包小程序app uniapp前端+全开源+独立版

简述 首先 圈子系统的核心是基于共同的兴趣或爱好将用户聚集在一起&#xff0c;这种设计使得用户能够迅速找到与自己有共同话题和兴趣的人。 其次 圈子系统提供了丰富的社交功能&#xff0c;如发帖、建圈子、发活动等&#xff0c;并且支持小程序授权登录、H5和APP等多种形式…

dfs板子

递归实现排列 留着明早省赛之前看 #include<iostream> using namespace std; int arr[10010]; int brr[10010]; int n,k; void dfs(int num){if(num > n){for(int i 1;i < n;i){cout << arr[i] << " ";}cout << endl;return;}for(in…

C# winform实现搜索读取已安装的路径

最近在开发winform窗体应用简单的桌面插件,需求是要点击按钮,就可打开相应程序软件但问题在于每个人电脑上的软件安装路径不同所以涉及到读取路径的的问题. 这位兄台写的播客解决了我的问题,甚是不错. ↓↓↓ 解决方案

二、计算机网络物理层基础知识

一、物理层 物理层接口特性&#xff1a;解决如何在连接各种计算机传输媒体上的传输数据比特流&#xff0c;而不是指具体的传输媒体 物理层的主要任务 &#xff1a;确定与传输媒体接口有关的一些特性>定义标准 1、机械特性&#xff1a;定义物理连接的特性&#xff0c;规定物理…

golang kafka sarama源码分析

一些理论 1.topic支持多分区&#xff0c;每个分区只能被组内的一个消费者消费&#xff0c;一个消费者可能消费多个分区的数据&#xff1b; 2.消费者组重平衡的分区策略&#xff0c;是由消费者自己决定的&#xff0c;具体是从消费者组中选一个作为leader进行分区方案分配&#…

人员抽烟AI检测算法原理介绍及实际场景应用

抽烟检测AI算法是一种基于计算机视觉和深度学习技术的先进工具&#xff0c;旨在准确识别并监测个体是否抽烟。该算法通过训练大量图像数据&#xff0c;使模型能够识别出抽烟行为的关键特征&#xff0c;如烟雾、手部动作和口部形态等。 在原理上&#xff0c;抽烟检测AI算法主要…

【Linux系列】Linux判断架构信息

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

K8s: 裸机初始化Kubernetes集群环境

环境准备 这里要先准备 linux 环境&#xff0c;提供一下几种方案1 &#xff09;在云产品上购买一台裸机2 &#xff09;选择一台刚安装好的 linux 服务器3 &#xff09;选择虚拟机安装 linux这里&#xff0c;我选择linux的环境为 centos 在安装了 centos 的裸机上进行搭建 1 &…

【QT入门】 Qt自定义控件与样式设计之QPushButton实现鼠标悬浮按钮弹出对话框

往期回顾&#xff1a; 【QT入门】 Qt自定义控件与样式设计之qss选择器-CSDN博客 【QT入门】 Qt自定义控件与样式设计之QLineEdit的qss使用-CSDN博客 【QT入门】Qt自定义控件与样式设计之QPushButton常用qss-CSDN博客 【QT入门】 Qt自定义控件与样式设计之QPushButton实现鼠标悬…

scipy.signal.cwt 与 pywt.cwt 使用记录

scipy.signal.cwt 该代码中widths以及freq计算公式来源于scipy.signal.morlet2函数官方案例 from scipy.signal import morlet, morlet2 from scipy import signal import matplotlib.pyplot as pltsignal_length 2000 fs 1000# 生成信号数据 time np.arange(0, signal_leng…

黄仁勋揭秘EIOFS(未来成功早期指标)英伟达成为最伟大AI企业的核心奥义

黄仁勋揭秘EIOFS(未来成功早期指标&#xff09;英伟达成为最伟大AI企业的核心奥义 原创 AI 吴厂长 AI 吴厂长 2024-04-02 00:12 上海 黄仁勋&#xff1a;你应该寻找未来成功的早期指标&#xff0c;而且越早越好。 原因是你想尽早看到自己正走在正确的方向上。 有个短语叫EIO…

Go语言中工作负载类型对并发的影响

在实际工作开发中我们需要根据工作负载是CPU密集型还是I/O密集型,使用不同的方式来解决问题。下面我们先来看这些概念,然后再讨论其影响。 在程序执行时,工作负载的执行时间会受以下因素限制: CPU的速度--例如,运行归并排序算法。工作负载被称为CPU密集型。I/O速度--例如…

Ubuntu 点击图标窗口最小化

本文所使用的 Ubuntu 系统版本是 Ubuntu 22.04 ! 用过 Ubuntu 系统的都知道&#xff0c;点击任务栏上的图标&#xff0c;它只能打开应用&#xff0c;而不能最小化应用。我希望点击图标能让窗口最小化这种效果&#xff0c;那该如何做呢&#xff1f; # 打开终端&#xff0c;输入如…

Docker-Compose配置文件docker-compose.yml详解

一份标准的docker-compose.yml文件应该包含version、services、networks三大部分&#xff0c;其中最关键的就是services和networks两个部分。 Compose和Docker兼容性&#xff1a; Compose 文件格式有3个版本,分别为1, 2.x 和 3.x 目前主流的为 3.x 其支持 docker 1.13.0 及其以…

C++---vector容器

是STL容器中的一种常用的容器&#xff0c;由于其大小(size)可变&#xff0c;常用于数组大小不可知的情况下来替代数组。vector容器与数组十分相似&#xff0c;被称为动态数组。时间复杂度为O&#xff08;1&#xff09;。 数组数据通常存储在栈中&#xff0c;vector数据通常存储…

C++ 二重指针

一 指向指针的指针 如果在一个指针变量中存放的是另一个变量的指针的地址&#xff0c;称该指针为指向指针的指针&#xff0c;即二重指针。

无线通信:调制(Modulation)方式

什么是调制方式 调制方式就是将信源信息&#xff08;要传输的信息&#xff09;加载到载波波形上&#xff0c;通过改变载波的某些特性来代表这些信息。通常&#xff0c;传统模拟信号有三种最基本的调制方式&#xff1a;改变幅度的叫调幅&#xff08;AM&#xff09;&#xff0c;…

2.1 LeetCode总结(基本算法)_DFS

1.4 练习 104. 二叉树的最大深度 int maxDepth(struct TreeNode *root, int len) {if (root NULL) {return len;}return fmax(maxDepth(root->left, len1), maxDepth(root->right, len1)); }二叉树最大深度就是基本的递归思路的求解&#xff0c; 手法主要是递归下去之…

C语言基础(三)

C语言基础 三大结构顺序结构选择结构单分支选择结构双分支选择结构多分支选择结构if ...else if....elseswitch语句 循坏结构for循环表达式1可以省略吗&#xff1f;表达式2可以省略吗&#xff1f;表达式3可以省略吗&#xff1f;for循坏的嵌套 while循环do while循坏while与do w…

android支付宝接入流程

接入前准备 接入APP支付能力前&#xff0c;开发者需要完成以下前置步骤。 本文档展示了如何从零开始&#xff0c;使用支付宝开放平台服务端 SDK 快速接入App支付产品&#xff0c;完成与支付宝对接的部分。 第一步&#xff1a;创建应用并获取APPID 要在您的应用中接入支付宝…