今天新开了一个专栏,打算把平时整理的一些力扣刷的题写一写......佛系更新,佛系布局。
本文2道题都是关于动态规划思想的,思路也相近,所以做一个整理。
目录
爬楼梯
假设你正在爬楼梯。需要
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 阶
思路
我的思路是这样的:设想出发点为第0阶,一共有n阶。那么建立长度为n+1的数组res,记录从第0-n阶到达第n阶的方法数。显然res的最后三位分别是2、1、0,然后向前遍历。在第x阶出发,要么走一阶到达第x+1阶,然后就有res[x+1]种方法;要么走2阶到达第x+2阶,然后就有res[x+3]阶。依次向前,计算得到res[0]就是从原点出发可能的方法数。
代码
class Solution {
public int climbStairs(int n) {
if(n<=3){
return n;
}
// 记录从该台阶出发到达第n阶的方法数
// 0 - n代表0阶 - n阶
int[] res=new int[n+1];
res[n]=0;
res[n-1]=1;
res[n-2]=2;
for(int i=n-3;i>=0;i--){
res[i]=res[i+1]+res[i+2];
}
return res[0];
}
}
最小花费爬楼梯
给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费。
示例1:
输入:cost = [10,15,20]
输出:15
解释:你将从下标为 1 的台阶开始。- 支付 15 ,向上爬两个台阶,到达楼梯顶部。
总花费为 15 。
示例2:
`输入:cost = [1,100,1,1,1,100,1,1,100,1]`
`输出:6`
`解释:你将从下标为 0 的台阶开始。`- `支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。`
- `支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。`
- `支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。`
- `支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。`
- `支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。`
- `支付 1 ,向上爬一个台阶,到达楼梯顶部。`
`总花费为 6 。`
思路
这道题与上一道题很类似,但也有区别。主要体现在,上一道题一定是从第0阶(第1阶之前)到第n阶;本题是,可以从下标为0或1的台阶出发,最终到达最高。注意,本题中,只要脚踩某个台阶,花费中就要包含它。例如,从下标为n-2的阶经过下标为n-1的阶到达终点,相当于踩了n-2、n-1,因此花费是cost[n-2]+cost[n-1];从下标为n-2的阶直接到达终点,相当于踩了n-2,跨过了n-1,因此花费是cost[n-2]。且从任意一阶出发,费用一定包含出发阶的花费。
其余的思路就差不多了。从后往前遍历,计算从该阶出发的最小花费,最终得到从下标为0和1的阶出发的最小花费,取最小值即可。
代码
class Solution {
public int minCostClimbingStairs(int[] cost) {
int n=cost.length;
if(n==1){
return cost[0];
}
if(n==2){
return cost[0]<cost[1]?cost[0]:cost[1];
}
// 记录从第i阶开始的最小花费
// 从下标为0的台阶到下标为n-1的台阶
// 只要经过该台阶,花费中就包含它
int[] minLs=new int[n];
minLs[n-1]=cost[n-1];
minLs[n-2]=cost[n-2];
for(int i=n-3;i>=0;i--){
minLs[i]=(cost[i]+minLs[i+1])<(cost[i]+minLs[i+2])?(cost[i]+minLs[i+1]):(cost[i]+minLs[i+2]);
}
return minLs[0]<minLs[1]?minLs[0]:minLs[1];
}
}