【Leetcode】70. 爬楼梯

题目来源

70. 爬楼梯

题目描述

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

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

示例 1:

输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。

  1. 1 阶 + 1 阶
  2. 2 阶

示例 2:

输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。

  1. 1 阶 + 1 阶 + 1 阶
  2. 1 阶 + 2 阶
  3. 2 阶 + 1 阶

提示:

1 <= n <= 45

知识点: 动态规划、数学

题目解析

问题分析

题目是一道经典的爬楼梯问题,每次你可以爬1或2个台阶,问有多少种不同的方法可以爬到楼顶。

以下分析以10个阶梯距离

问题一: 当我们从最后来看,如果只差最后一步就可以走到第10个阶梯,有几种情况?

情况一:剩一个阶梯,从9到10

情况二,剩两个阶梯,从8到10

也就是说,要想到达最后一个阶梯,最后一步要么是还剩一个阶梯,要么还剩两个阶梯

总结:

  • 那么对于动态规划类型,首先我们就需要转换视角,先从最后来看

问题二:假设到达第8层的走法有F(8)种,到达第9层的有F(9)种,那么到达第10层的走法有多少种?

那么基于问题一的分析,我们能知道到达第10层的两种情况分别是8到10和9到10,那么就是说

到达第10层的走法=到达第8的走法数量+到达第9层的走法数量

即F(10) = F(9) + F(8)

问题三:既然我们已经知道F(10) = F(9) + F(8),那么F(9)、F(8)如何求?

这个也很简单,我们假设10层是最后一层,他的走法有F(9) + F(8)种。那么同理我们可以假设9是最后一层,那么他的走法就是前面两层的和,也就是F(8) + F(7)种,第8层也同理。

那么我们就可以得出:

  • F(9) = F(8) + F(7);
  • F(8) = F(7) + F(6);
  • F(3) = F(1) + F(2)

这里就体现了动态规划的思想:把一个复杂的问题分阶段的进行简化,逐步简化成简单的问题。

那么当只有1级台阶和2级台阶的时候有几种解法呢?显然是1和2。

所以可以得出:

  • F(1)=1
  • F(2)=2
  • F(n)=F(n-1)+F(n-2) (n>=3)

这一步的核心就是:从后往前推,看和前面有什么的关系

动态规划的三个重要概念

最优子结构、边界、状态转移方程

一、最优子结构

  1. 定义:一个问题具有最优子结构性质是指该问题的最优解可以由其子问题的最优解组合而成。也就是说,如果一个问题的最优解包含了子问题的最优解,那么这个问题就具有最优子结构性质。
  2. 示例:例如在求解斐波那契数列问题中,斐波那契数列的第(n)项(F(n))可以由(F(n - 1))和(F(n - 2))相加得到。如果我们已经知道了(F(n - 1))和(F(n - 2))的最优解(即它们各自的值),那么就可以通过简单的相加得到(F(n))的最优解。这就体现了斐波那契数列问题具有最优子结构性质。

二、边界

  1. 定义:边界是指问题规模最小的情况,在这种情况下可以直接得到问题的解,而不需要再进行进一步的划分和求解。边界条件通常是动态规划算法的起点,它为问题的求解提供了基础。
  2. 示例:还是以斐波那契数列为例,当(n = 0)时,(F(0)=0);当(n = 1)时,(F(1)=1)。这两个值就是斐波那契数列问题的边界条件。在求解斐波那契数列的其他项时,我们可以从这些边界条件开始,逐步推导出更大规模问题的解。

三、状态转移方程

  1. 定义:状态转移方程是动态规划算法的核心,它描述了问题的状态之间的转移关系。通过状态转移方程,我们可以从已知的状态推导出未知的状态,从而逐步求解出问题的最优解。
  2. 示例:对于斐波那契数列问题,状态转移方程为(F(n)=F(n - 1)+F(n - 2))。这个方程明确了斐波那契数列中不同项之间的关系,我们可以根据这个方程,从边界条件开始,逐步计算出斐波那契数列的其他项。

  • 上面我们知道F(10) = F(9) + F(8),因此F(9)F(8)F(10)的最优子结构
  • 当只有1级台阶或2级台阶的时候,我们可以直接得出结果,无需继续简化。我们称F(1)或者F(2)是问题的【边界】。如果一个问题没有边界,将永远无法得到有限的结果
  • F(n) = F(n - 1) + F(n - 2)是阶段与阶段之间的状态转移方程。这是动态规划的核心,决定了问题的每一个阶段与下一个阶段的关系

题目求解(从上到下)

递归求解

    public static int climbStairs(int n) {if (n < 1){return 0;}if (n == 1){return 1;}if (n == 2){return 2;}return climbStairs(n - 1) + climbStairs(n - 2);}

备忘录算法

画出二叉树可以发现,有些相同的参数被重复计算了

如果想要避免重复计算,我们可以用创建一个哈希表,每次把不同的参数的计算结果存入哈希。当遇到相同参数时,再从哈希表中取出,就不用重复计算了。这个算法有个专有名词,备忘录算法

class Solution {// 递归时由大量的重复运算,我们可以用一个map把原来算出来的值存起来以便以后使用static Map<Integer, Integer> maps =  new HashMap<Integer, Integer>();public int climbStairs(int n) {if (n < 1){return 0;}if (n == 1){return 1;}if (n == 2){return 2;}if (maps.containsKey(n)){  return maps.get(n);}else{int value = climbStairs(n - 1) + climbStairs(n - 2);maps.put(n, value);return value;}}
}

集合map是一个备忘录。当每次需要计算F(N)的时候,会首先从map中寻找匹配元素。如果map中存在,就直接返回结果,如果map中不存在,就计算出结果,存入备忘录中。

动态规划

动态规划五部曲

  1. 确定dp数组以及下标的含义
  • dp[i]:爬到第i层楼梯,有dp[i]种方法
  1. 确定递推公式
  • 从dp[i]的定义可以看出,dp[i] 可以有两个方向推出来。
    • 首先是dp[i - 1],上i-1层楼梯,有dp[i - 1]种方法,那么再一步跳一个台阶不就是dp[i]了么。
    • 还有就是dp[i - 2],上i-2层楼梯,有dp[i - 2]种方法,那么再一步跳两个台阶不就是dp[i]了么。
  • 那么dp[i]就是 dp[i - 1]与dp[i - 2]之和!即dp[i] = dp[i - 1] + dp[i - 2]
  • 在推导dp[i]的时候,一定要时刻想着dp[i]的定义,否则容易跑偏。
  1. dp数组如何初始化
  • 回顾一下dp[i]的定义:爬到第i层楼梯,有dp[i]中方法
  • 需要注意的是:题目中说了n是一个正整数,题目根本就没说n有为0的情况。所以本题其实就不应该讨论dp[0]的初始化!
  • 因此,结论是:不考虑dp[0]如果初始化,只初始化dp[1] = 1,dp[2] = 2,然后从i = 3开始递推,这样才符合dp[i]的定义。
  1. 确定遍历顺序
  • 从递推公式dp[i] = dp[i - 1] + dp[i - 2];中可以看出,遍历顺序一定是从前向后遍历的
  1. 举例推导dp数组

举例当n为5的时候,dp table(dp数组)应该是这样的

代码

class Solution {public int climbStairs(int n) {if(n<=1) return n;int[] dp = new int[n + 1]; // dp[0]不考虑// 含义:第i个台阶有dp[i]种方法dp[1] = 1;dp[2] = 2;for (int i = 3; i <= n; i++) {dp[i] = dp[i - 1] + dp[i - 2];}return dp[n];}
}
  • 时间复杂度:O ( n )
  • 空间复杂度:O ( n )

动态规划本质上就是填表的过程

类似题目

题目

思路

leetcode:70. 爬楼梯 Climbing Stairs

动态规划

leetcode:746. 使用最小花费爬楼梯 Min Cost Climbing Stairs

动态规划

leetcode:509. 斐波那契数列 Fibonacci Number

动态规划

leetcode:91. 解码方法Decode Ways

leetcode:639.*可以匹配多个字符时,有多少解码方法 II Decode Ways II

leetcode:842. 将数组拆分成斐波那契序列,返回一个成功的组合 Split Array into Fibonacci Sequence

回溯

leetcode:306. 字符串是否能切割成斐波那契序列 Additive Number

leetcode:873. 最长的斐波那契序列长度 Length of Longest Fibonacci Subsequence

Coin Change

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

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

相关文章

webpack5 构建优化方案看这篇就够了!【Node.js进阶】

无论在面试还是内部晋升&#xff0c;webpack 构建优化方案 一直都是非常重要的部分。 webpack5构建加持 一、项目完成目标二、搭建项目1. 安装koa、koa/router &#xff08;如果已经配置可路过&#xff09;2. 创建入口文件3. 安装构建依赖4. 在项目根目录添加 .babelrc 文件5. …

一般在写SQL时需要注意哪些问题,可以提高查询的效率?

很多人写SQL按照自己喜好&#xff0c;没有规则意识&#xff0c;这对于自主查询影响不大&#xff0c;你爱怎么搞就怎么搞&#xff0c;一旦涉及到提交任务或团队共享&#xff0c;就不能乱写了&#xff0c;会浪费资源影响到开发效率&#xff0c;严重的甚至会服务器瘫痪。 提几个关…

进程的重要函数

进程的重要函数: fork函数 了解fork函数 通过调用fork()函数&#xff0c;则会产生一个新的进程。调用fork()函数的进程叫做 父进程&#xff0c;产生的新进程则为子进程。 其编码过程: 1.函数功能: 函数头文件 #include <sys/types.h> #include <unistd.h> 函数…

运用Java实现倒计时功能

这个功能其实是比较好实现的&#xff0c;一般来说java中实现倒计时有两种方法&#xff1a; 1、使用 scheduledexecutorservice创建一个可重复执行的任务&#xff0c;直到时间到&#xff1a; ScheduledExecutorService 是 Java 中一种用于安排延迟或定期任务的工具。我们可以使…

云计算第四阶段------CLOUD Day4---Day6

Cloud DAY4 项目架构图&#xff1a; 环境准备&#xff1a; 主机名称IP地址配置logstash192.168.1.27最低配置4核8G #书接上文&#xff0c;我们在华为云平台租了几台云服务器&#xff0c;这次买一台性能好的服务器&#xff0c;作为logstash软件部署的载体。 今天给小伙伴们带来…

低代码门户技术:构建高效应用的全新方式

什么是低代码门户技术&#xff1f; 低代码门户技术是一种利用低代码平台构建企业门户网站或应用的技术。门户通常是企业内部和外部用户访问信息和应用的集中平台。低代码门户技术通过图形化界面和预置组件&#xff0c;允许用户快速搭建和定制这些门户平台&#xff0c;而无需深…

TCP并发服务器的实现

一请求一线程 问题 当客户端数量较多时&#xff0c;使用单独线程为每个客户端处理请求可能导致系统资源的消耗过大和性能瓶颈。 资源消耗&#xff1a; 线程创建和管理开销&#xff1a;每个线程都有其创建和销毁的开销&#xff0c;特别是在高并发环境中&#xff0c;这种开销…

性能测试的复习3-jmeter的断言、参数化、提取器

一、断言、参数化、提取器 需求&#xff1a; 提取查天气获取城市名请求的响应结果&#xff1a;城市对查天气获取城市名的响应结果进行响应断言和json断言对查天气获取城市名添加用户参数 1、步骤 查看天气获取城市名 json提取器&#xff08;对响应结果提取、另一个接口请求…

简单了解微服务--黑马(在更)

认识微服务 单体架构 不适合大型复杂项目 微服务架构 将单体结构的各个功能模块拆分为多个独立的项目 拆取的独立项目分别开发&#xff0c;在部署的时候也要分别去编译打包&#xff0c;分别去部署&#xff0c;不同的模块部署在不同的服务器上&#xff0c;对外提供不同的功能…

小间距LED显示屏的技术原理分析

在现代显示技术领域&#xff0c;小间距LED显示屏以其卓越的显示效果和灵活的应用场景&#xff0c;逐渐成为市场的新宠。本文将深入探讨小间距LED显示屏的技术原理&#xff0c;分析其在显示领域的应用优势。 A、小间距LED显示屏的基本概念 小间距LED显示屏是指LED灯珠之间的间距…

linux hadoop-3.3.6 hbase-2.5.7

软件下载 hadoop https://dlcdn.apache.org/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz 可以直接下载到本地&#xff0c;也可以直接下载进虚拟机中 如果速度较慢&#xff0c;可以用&#xff1b;另一个 wget https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common…

spring-boot-maven-plugin插件打包和java -jar命令执行原理

文章目录 1. Maven生命周期2. jar包结构2.1 不可执jar包结构2.2 可执行jar包结构 3. spring-boot-maven-plugin插件打包4. 执行jar原理 1. Maven生命周期 Maven的生命周期有三种&#xff1a; clean&#xff1a;清除项目构建数据&#xff0c;较为简单&#xff0c;不深入探讨&a…

spring容器创建bean过程中使用到的几个factory

文章目录 前述BeanFactoryFactoryBeanObjectFactory 前述 spring我们可以理解为一个帮我们管理bean的容器&#xff0c;使用spring框架之前创建bean都是通过new的方式&#xff0c;使用spring框架之后&#xff0c; 我们只需要告诉spring框架我们有那些bean&#xff0c;它会帮我们…

k8s证书过期处理

证书一共分为 根CA&#xff08;ca.crt&#xff09; master各组件的证书&#xff08;包括etcd、apiserver、front-proxy、controller-manager等各种&#xff09; kubelet证书 k8s证书有效期说明&#xff1a; 1、原生版本有效期master节点&#xff1a; /etc/kubernetes/ssl/…

YOLOv10改进系列,YOLOv10损失函数更换为Powerful-IoU(2024年最新IOU),助力高效涨点

改进前训练结果: 改进后的结果: 摘要 边界框回归(BBR)是目标检测中的核心任务之一,BBR损失函数显著影响其性能。然而,观察到现有基于IoU的损失函数存在不合理的惩罚因子,导致回归过程中锚框扩展,并显著减缓收敛速度。为了解决这个问题,深入分析了锚框扩展的原因。针…

基于 K8S kubernetes 的常见日志收集方案

目录 1、日志对我们来说到底重不重要&#xff1f; 2、常见的日志收集方案 2.1 EFK 2.2 ELK Stack 2.3 ELKfilebeat 2.4 其他方案 2、elasticsearch组件介绍 3、filebeat组件介绍 3.1 filebeat和beat关系 3.2 filebeat是什么&#xff1f; 3.3 Filebeat工作原理 3.4 …

ELFK日志分析平台,架构和通信

整个架构&#xff0c;加上跳板机&#xff0c;总共12台机器 技术方案&#xff1a; 1. 配置nfs服务器&#xff0c;为web集群提供共享网络文件系统 # 部署 NFS 服务 [rootnfs ~]# dnf install -y nfs-utils [rootnfs ~]# vim /etc/exports /var/webroot 192.168.1.0/24(rw,…

xml重点笔记(尚学堂 3h)

XML:可扩展标记语言 主要内容(了解即可) 1.XML介绍 2.DTD 3.XSD 4.DOM解析 6.SAX解析 学习目标 一. XML介绍 1.简介 XML(Extensible Markup Language) 可扩展标记语言&#xff0c;严格区分大小写 2.XML和HTML XML是用来传输和存储数据的。 XML多用在框架的配置文件…

剖析 MySQL 数据库连接池(C++版)

目录 ☀️0. 前言 &#x1f324;️1. 数据库连接池概述 ⛅1.1 服务器与数据库交互 ⛅1.2 MySQL 数据库网络模型 ⛅1.3 MySQL 连接驱动安装 ⛅1.4 同步&#xff08;synchronous&#xff09;连接池与异步&#xff08;asynchronous&#xff09;连接池 ⛅1.5 同步连接池和异…

记录开发一个英语听力训练网站

背景 在当前全球经济衰退的背景下&#xff0c;IT相关的工作在国内的竞争也是越来越激烈&#xff0c;为了能够获得更多的可能性&#xff0c;英语的学习也许能为程序员打开一扇新的窗户&#xff0c;比如很多远程的工作尤其是国际化背景的工作团队&#xff0c;英语的协作沟通是必…