leetcode 746.爬楼梯的最小代价(从暴力递归到动态规划)

使用最小代价爬楼梯 你需要爬上一个N层的楼梯,在爬楼梯过程中, 每阶楼梯需花费非负代价,第i阶楼梯花费代价表示为cost[i], 一旦你付出了代价,你可以在该阶基础上往上爬一阶或两阶。 你可以从第 0 阶或者 第 1 阶开始,请找到到达顶层的最小的代价是多少。 N和cost[i]皆为整数,且N∈[2,1000],cost[i]∈[0, 999]。 输入描述: 输入为一串半角逗号分割的整数,对应cost数组... 阅读详情

题目:

On a staircase, the i-th step has some non-negative cost cost[i] assigned (0 indexed).

Once you pay the cost, you can either climb one or two steps. You need to find minimum cost to reach the top of the floor, and you can either start from the step with index 0, or the step with index 1.

题解:

题目要求起点是0或1下标位置处,走到最顶楼梯花费的最小代价是多少。cost[i]=j表示第i节楼梯需要花费的代价是j。每到一层可以跳一阶到下一个楼梯,也可以跳二阶到下下个楼梯。

输入输出描述:

input:cost=[10,15,20]。

output:15

解释:

      最小代价是15。具体来说,从1下标开始,此时需要花费15,然后跳2阶到顶层(跳1阶到下标2位置,花费代价增加)。

解题思路:

第一个想法是暴力递归(说实话深度优先搜索自己个人已经比较熟练了,很多时候看到这个题目第一想法就是暴力递归,深度优先搜索,已经形成惯性思维了)。

深度优先搜索的思路是:“不到南墙不回头”。具体来说,深度优先搜索并不管最终决策如何,只管当前决策有几种可能性,就搜索多少次。

在这个地方也总结一下暴力递归的套路:

暴力递归模板:

void depthSearch(a,b):

    if(condition):

          // 达到递归终止条件(也就是到了“南墙”),进行相应的操作,比如更新结果数组,更新其他变量

    else

    //状态改变

    depthSearch(a+1,b)

    //状态恢复(也就是“回头”的过程)

基本上深度优先搜索就是这么个流程走,在这个函数的模板中,我定义了两个参数a,b,实际应用中可以有多个参数,而且a,b参数类型也可以多种多样,有时候为了保存结果变量,比如,步数最少,代价最小,这个时候参数就可以声明成一个int[]result,它的长度是1,因为java中基本数据类型参数传值是值传递,对形参的改变不影响实参,有些时候我们需要对某一层递归的参数进行全局修改,因此可以考虑使用一个长度为1的数组,这个技巧一定要学会。具有类似性质的技巧还有StringBuilder(需要对String变量进行修改)。

第二个需要考虑的点是,状态改变,继续搜索,状态恢复这三个步骤怎么理解。

在上面的部分我已经说过深度优先搜索只关注当前如何决策,其实决策的过程就是状态改变的过程,当前决策完毕,就开始继续深度搜索,那么,为什么需要状态恢复这个过程呢?

我们知道,由于深度优先搜索只关注当前的决策,对于全局是否是最优或者最佳决策深度优先并不关心,因此,就需要遍历所有的情况,当前位置决策结束后,把状态恢复,就可以继续进行搜索。

好了,理论部分就在这里,下面直接给出代码,结合代码与理论解释深度优先搜索的过程。

    // totalPay表示走到i位置之前需要的总的花费
    // i表示当前走到的位置
    // cost数组表示每一阶楼梯花费的代价
    // result是一个长度为1的整形数组,表示最小的花费,由于它需要全局修改,
    // 如果只声明一个int 变量,由于java值传递的特性,在下一次递归调用时
    // 做不到全局修改,因此需要弄成数组,这个技巧一定要会
    public void depthSearch(int totalPay,int i,int[]cost,int[]result){
        if(i>=cost.length){  //这个地方就是撞到“南墙”,也就是递归结束条件
        // 可能有人会问,为什么结束条件是i>=cost.length,i有可能大于cost.length吗
        // 回答是,可能,我们知道cost数组是每个楼梯在某一层的花费代价,也就是说
        // cost的长度代表了有几阶楼梯,如果搜索到i>=cost.length,说明早就到了顶
        // 端,按照题意确实应该停止,那么什么情况会出现i>cost.length呢。
        // 按照题目意思,在每一阶楼梯都可以往上(或者说往右)走一步或者两步,如果
        // 我在最后一阶楼梯走一步,那么就会到达cost.lenth位置,如果在最后一阶楼
        // 梯走两步,就会到达cost.length+1位置,也就是到了>cost.length的情况
            if(totalPay<result[0])
                result[0]=totalPay;
        // 上述部分的第二个if(totalPay<result[0])作何解释呢?
        // 如果i>=cost.length,说明此时已经到达楼顶,也就是说搜索到一条合法的路径
        // 我们比较当前这条路径的花费totalPay和已经搜索到的花费result[0]哪个更少
        // 继续更新result[0],result[0]始终保存着当前搜索到的合法路径中花费最小的。
        }
        else{
            // 从这个else开始,是递归调用,也就是深度优先搜索的过程
            totalPay+=cost[i];i++; // 状态改变,表示往上走一步(位置改变),其实还有一个变量也改变
            // 了,就是totalPay,表示花费增加了,因为走了当前位置i,就需要花费cost[i]
            depthSearch(totalPay, i, cost, result); // 深度搜索
            // 在这里,我为了演示状态改变和恢复的过程,代码多写了几行
            // 其实更简洁的语句是depthSearch(totalPay+cost[i], i+1, cost, result); 
            i--; // 状态恢复
            i+=2; // 状态改变,表示往上走两步
            depthSearch(totalPay+cost[i], i, cost, result);
            i-=2; // 状态恢复
        }
    }
    public int minCostClimbingStairs(int[] cost) {
        if(cost==null||cost.length==0)
            return 0;
        int[]result=new int[1];
        result[0]=Integer.MAX_VALUE;
        depthSearch(0, 0, cost, result); // 题目中说了可以从0开始,也可以从1开始
        depthSearch(0, 1, cost, result);
        System.out.println(result[0]);
        return result[0];
    }

非常兴奋提交,然后,喜闻乐见的超时了。

既然暴力递归超时了,一个想法就是将其转化成动态规划,那么,动态规划该如何设计呢?

动态规划思想主要是以空间换时间,在这道题中,就是使用一个数组dp,它和cost具有相同的长度

dp[i]=j表示走到位置i需要的最小花费为j

我们知道,每一个位置在到下一个位置的时候都有两种情况,要么走一步,也就是走到i+1的位置,

要么走两步,也就是走到i+2的位置,换句话说,当前的位置i一定是从i-1走一步过来或者是i-2走两

步过来的,只有可能是这两种情况,由于dp[i]需要是最小花费代价,因此上述两种情况取最小值就

是dp[i]的值,不难写出下面的代码

    public int minCostClimbingStairs(int[] cost) {
        if(cost==null||cost.length==0)
            return 0;
        if(cost.length==1)
            return cost[0];
        if(cost.length==2)
            return Math.min(cost[0], cost[1]);
        int[]dp=new int[cost.length];
        dp[0]=cost[0];
        dp[1]=cost[1];
        int i;
        for(i=2;i<dp.length;i++)
            dp[i]=Math.min(dp[i-1], dp[i-2])+cost[i];
        i=dp.length-1;
        return Math.min(dp[i], dp[i-1]);
    }

总结:很多时候,动态规划都是因为暴力递归耗时太长而想出来的优化算法,

以空间换时间,从而降低时间复杂度。

递推之爬楼梯 爬楼梯 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Description 小明是个非常无聊的人,他每天都会思考一些奇怪的问题,比如爬楼梯的时候,他就会想,如果每次可以上一级台阶或者两级台阶,那么上 n 级台阶一共有多少种方案? Input 输入包含多组测试数据,对于每组测... 阅读详情

相关推荐

LeetCode——746. 使用最小花费爬楼梯

目录题目1.链接2.题目描述3.解题思路4.题解 题目 1.链接 746. 使用最小花费爬楼梯. 2.题目描述 3.解题思路 动态规划 这里的每一级楼梯都是有价格的,想要跨过它,就要交保护费,而我们每次可以从前一个楼梯或者前两个楼梯爬上来,所以,不难写出动态规划方程: 状态定义:dp[i] 表示到达第 i 级楼梯所需要的最小代价(注意:是到达,还没有跨过)。 转移方程:dp[i] = min(dp[i-2]+cost[i-2], dp[i-1]+cost[i-1]),要想到达 i,要么交 i-2 的保护费

qq_59708493的博客 776

C++递推经典案例No.3——爬楼梯的最小代价

数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始)。每当爬上一个阶梯都要花费对应的体力值,一旦支付了相应的体力值,就可以选择向上爬一个阶梯或者爬两个阶梯。在开始时,你可以选择从下标为 0 或 1 的元素作为初始阶梯。,而对于本题,由于一次性可以跳1个或者2个,所以可以转化为:从前一个和前两个到当前位置,哪个所花费的体力值。,如果想要爬到最顶层(也就是遍历到下标越界的地步)。例如,想到达下标为2的6,要么从0开始,要么从1开始,相当于就是。

软工科班,擅长Matlab、C++、微信小程序开发 880

用Arduino Uno和纸板做个扫地机器人?手把手教你复刻一个低成本DIY方案(附完整代码)

本文详细介绍了如何用Arduino Uno和纸板制作一款低成本DIY扫地机器人,涵盖材料准备、机械结构设计、电路系统搭建和智能清扫算法实现。通过开源硬件和日常废弃物,打造极致性价比的创客项目,适合初学者学习电子和编程。

weixin_42531588的博客 267

详细图解动态规划leetcode_746. 使用最小花费爬楼梯--简单动态规划

动态规划leetcode_746--简单问题描述思路描述图解思路代码实现总结写在最后 问题描述 数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始)。 每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯。 请你找出达到楼层顶部的最低花费。在开始时,你可以选择从下标为 0 或 1 的元素作为初始阶梯。 示例 1: 输入:cost = [10, 15, 20] 输出:15 解释:最低花费是从 cost

Adorablenewbaby的博客 514

ECU-TEST新手入门:从软件申请到第一个测试包创建的完整保姆级流程

本文详细介绍了ECU-TEST软件从申请试用、安装配置到创建第一个测试包的完整流程。针对新手用户,提供分步指导,包括界面认知、测试组件添加、变量定义及执行结果分析,帮助快速掌握汽车电子测试工具的基本操作。特别说明试用授权的两种获取方式和安装注意事项。

weixin_30606461的博客 481

2023年高教社杯 | 2023年高教社杯全国大学生数学建模思路(A题思路、C题思路)

2023年高教社杯 | 2023年高教社杯全国大学生数学建模思路(A题思路、C题思路)

前程算法屋的博客 624

动态规划【最小代价爬楼梯】

给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。请你计算并返回达到楼梯顶部的最低花费。示例 1:输入:cost = [10,15,20]输出:15解释:你将从下标为 1 的台阶开始。输入:cost = [1,100,1,1,1,100,1,1,100,1]输出:6解释:你将从下标为 0 的台阶开始。来源:力扣(LeetCode)

周小兔的大管家的博客 478

华为OD机试新系统真题【仓库盘点】

华为OD机试真题 新系统【仓库盘点】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题【仓库盘点】

qq_45776114的博客 570

Day 6.1 最小代价爬楼梯

problem describe: On a staircase, the i-th step has some non-negative cost cost[i] assigned (0 indexed). Once you pay the cost, you can either climb one or two steps. You need to find minimum cost t...

shine10076的博客 851

Ardupilot飞控姿态角与姿态角速度控制过程分析(超长篇)

目录 目录 摘要 1.代码控制过程分析 摘要 本节主要记录自己学习ardupilot飞控代码的姿态角速度的控制过程 1.代码控制过程分析 可以看出:AC_AttitudeControl *attitude_control; //指针对象 virtual void rate_controller_run() = 0;是AC_AttitudeContro...

陌城烟雨 1万+

基于Matlab生成并可视化多架飞机轨迹仿真(附源码)

这使我们可以轻松地对直线和恒定转弯进行建模,并具有额外的自由度,可以在直线段和曲线段之间平滑过渡。同样,空气中的物体会经历重力的影响,遵循抛物线(二次)路径。需要更多的航点来适应这些变化,但是轨迹的其余部分需要更少的点。第三个轨迹,如下所示,代表了一架速度更高的飞机。它由两个恒定的转弯组成,飞机在第二个转弯的中间减速。一旦知道(并设置了)物体穿过空间的物理路径,物体的速度作为行进距离的函数就通过三次埃尔米特插值来确定。在此示例中,学习了内部使用的插值符背后的概念,并展示了如何使用少量航点重现场景。

珞瑜的博客 5464

一文搞懂从爬楼梯到最小花费(力扣70,746)

动态规划算法(Dynamic Programming)是一种解决多阶段决策过程最优化问题的方法。它将问题分解为相互重叠的子问题,并通过解决子问题来解决整个问题。这种方法通常用于具有重叠子问题和最优子结构性质的问题。动态规划的基本思想是将原问题分解为相互重叠的子问题,并在解决这些子问题时进行存储,以避免重复计算。通过这种方式,可以大大减少计算量,提高算法效率。动态规划算法通常涉及两个关键步骤:定义状态和状态转移方程。定义状态: 确定问题中的状态变量,并定义状态之间的关系。

Huahua_1223的博客 2477

RK3399平台开发系列讲解(内核入门篇)1.1、通过sysfs清楚了解设备的系统状况

文章目录1、不敢高声语,恐惊天上人:sysfs目的2、窥一斑而知全豹:sysfs目录介绍3、千丝万缕:sysfs中要素的关系4、数据观星:sysfs中相关结构体 1、不敢高声语,恐惊天上人:sysfs目的 我们想通过sys下面的目录和文件清楚的了解跑Liunx系统的嵌入式设备的系统状况。 2、窥一斑而知全豹:sysfs目录介绍 sysfs把连接在系统上的设备和总线组织成为一个分级的文件,它们可以由用户空间存取,向用户空间导出内核的数据结构以及它们的属性。sysfs的一个目的就是展示设备驱动模型中各组件.

内核笔记 1万+

快手笔试题

题目:你需要爬上一个N层的楼梯,在爬楼梯的过程中,每阶楼梯需花费非负代价,第 i 阶楼梯花费代价表示cost[i],一旦你付出了代价,你可以在该阶梯基础上往上爬一阶或两阶。在开始时,你可以选择从第 0 阶或第 1 阶开始出发。请计算爬上楼层顶部的最低花费。 输入格式: 1,100,1,100,1,1,100,1,1 输出格式: 6 分析:动态规划。当前最小体力花费=mi...

weixin_33754065的博客 1267

自抗扰控制(ADRC)理论与工程实践:6.1 离散时间ADRC的推导

本文系统阐述了自抗扰控制(ADRC)的离散化方法,重点对比了前向欧拉法和基于零阶保持器(ZOH)的精确离散化两种方法。前向欧拉法计算简单但精度较低,稳定性受采样周期约束;ZOH法精度高但对大采样周期更鲁棒。文章详细推导了跟踪微分器、扩张状态观测器和控制律的离散形式,分析了采样周期选择的关键因素,为ADRC的数字实现提供了理论指导。

技术工作者 197

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

LeetCode算法心得——使用最小花费爬楼梯(记忆化搜索+dp)

状态转移思想。

晴天学长 930

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

最小代价爬楼梯_offer

你需要爬上一个N层的楼梯,在爬楼梯过程中, 每阶楼梯需花费非负代价,第i阶楼梯花费代价表示为cost[i], 一旦你付出了代价,你可以在该阶基础上往上爬一阶或两阶。 你可以从第 0 阶或者 第 1 阶开始,请找到到达顶层的最小的代价是多少。 N和cost[i]皆为整数,且N∈[2,1000],cost[i]∈[0, 999]。 public class Demo02 { ...

JZWen 538

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

leetcode 746 Min Cost Climbing Stairs

题目详情 On a staircase, the i-th step has some non-negative cost cost[i] assigned (0 indexed).Once you pay the cost, you can either climb one or two steps. You need to find ...

weixin_34380948的博客 277

动态规划--最小代价爬楼梯

1、题目:On a staircase, the i-th step has some non-negative cost cost[i] assigned (0 indexed).Once you pay the cost, you can either climb one or two steps. You need to find minimum cost to reach the top ...

qq_31307013的博客 982

Leetcode747 Min Cost Climbing Stairs(爬楼梯的最小代价)

题目:On a staircase, the i-th step has some non-negative cost cost[i] assigned (0 indexed).Once you pay the cost, you can either climb one or two steps. You need to find minimum cost to reach the top of

XINGKONG_04的博客 543

LeetCode 746最小代价爬楼梯

题目: 数组的每个索引做为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 cost[i]索引从0开始)。 每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯或者爬两个阶梯。 您需要找到达到楼层顶部的最低花费。在开始时,你可以选择从索引为 0 或 1 的元素作为初始阶梯。 示例 1: 输入: cost = [10, 15, 20] 输出: 15 解释: 最低花费是从c...

xiao1guaishou的博客 334

力扣:746. 使用最小花费爬楼梯

力扣:746. 使用最小花费爬楼梯,C++,动态规划

weixin_44788175的博客 394

爬楼梯问题

简述: 需要爬N层的楼梯,有max种爬楼梯方式,需要求算总共爬到N层 有几种方法 1. 回溯是比较直观的,就是一层一层向上叠加,走到顶层就是一种方法,得到结果 2. 一维动态规划的话, 就是用一个数组保留走过的楼层,比如最大步伐是3, 然后我现在考虑走到第10层有几种走法 就是 resultArray[10] = resultArray[ 10 - 1] + resultArray[10

霖林烟雨 2025

使用最小花费爬楼梯 (LeetCode - 746)

使用最小花费爬楼梯 描述 你需要爬上一个N层的楼梯,在爬楼梯过程中,每阶楼梯需花费非负代价,第i阶楼梯花费代价表示为cost[i],一旦你付出了代价,你可以在该阶基础上往上爬一阶或两阶。你可以从第0阶或者第1阶开始,请找到到达顶层的最小的代价是多少 N和cost[i]皆为整数,且N∈[2,1000],cost[i]∈[0,999] 输入 输入为一行整数,对应cost数组 输出 ...

SEVENY_的博客 1261

Leetcode 使用最小花费爬楼梯

746.使用最小花费爬楼梯 数组的每个索引做为一个阶梯,第i个阶梯对应着一个非负数的体力花费值cost[i](索引从0开始)。 每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯或者爬两个阶梯。 您需要找到达到楼层顶部的最低花费。在开始时,你可以选择从索引为 0 或 1 的元素作为初始阶梯。 示例1: 输入: cost = [10, 15, 20]...

weixin_41514525的博客 240
上一篇: LeetCode874:机器人路径模拟
下一篇: leetcode343. Integer Break
spencersong
博客等级 码龄9年 11粉丝 14原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值