Open azl397985856 opened 2 years ago
https://leetcode.com/problems/min-cost-climbing-stairs/
DP
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
len_cost = len(cost)
dp = [float("inf")] * 3
dp[0], dp[1] = cost[0], cost[1]
for i in range(2, len_cost):
j = i % 3
dp[j] = min(dp[j-2], dp[j-1]) + cost[i]
return min(dp[(len_cost-2)%3], dp[(len_cost-1)%3])
时间复杂度: O(N) 空间复杂度:O(1)
/**
* @param {number[]} cost
* @return {number}
* dp[i]=min(dp[i-1],dp[i-2])+cost[i]
*/
var minCostClimbingStairs = function(cost) {
let n = cost.length;
if (!cost || n === 0) {
return 0;
}
let dp = new Array(n + 1);
dp[0] = cost[0];
dp[1] = cost[1];
for(let i=2; i<n+1; i++) {
dp[i] = Math.min(dp[i-1],dp[i-2]) + (i === n ? 0 : cost[i])
}
return dp[n]
};
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
dp = [0] * (len(cost)+1)
dp[0], dp[1] = cost[0], cost[1]
for i in range(2, len(cost)+1):
dp[i] = min(dp[i-1], dp[i-2]) + (cost[i] if i != len(cost) else 0)
return dp[-1]
# time: O(N)
# space: O(1)
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
prev1 = cost[0]
prev2 = cost[1]
for i in range(2, len(cost)):
curr = min(prev1, prev2) + cost[i]
prev1 = prev2
prev2 = curr
return min(prev1, prev2)
Go Code:
func minCostClimbingStairs(cost []int) int {
for i := range cost {
if i <= 1 {
continue
}
cost[i] = min(cost[i-1], cost[i-2]) + cost[i]
}
return min(cost[len(cost)-1], cost[len(cost)-2])
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
复杂度分析
令 n 为数组长度。
记忆化搜索
class Solution {
public int minCostClimbingStairs(int[] cost) {
if (cost.length == 0) {
return 0;
}
if (cost.length == 1) {
return cost[0];
}
int[] minCosts = new int[cost.length];
minCosts[0] = cost[0];
minCosts[1] = cost[1];
for (int i = 2; i < cost.length; i++) {
minCosts[i] = cost[i] + Math.min(minCosts[i-1], minCosts[i-2]);
}
return Math.min(minCosts[minCosts.length-1], minCosts[minCosts.length-2]);
}
}
时间: O(n) \ 空间: O(n)
var minCostClimbingStairs = function(cost) {
const dp = []
dp[0] = cost[0]
dp[1] = cost[1]
const length = cost.length
for (let i = 2; i < length; i++) {
dp[i] = Math.min(dp[i - 1], dp[i - 2]) + cost[i]
}
return Math.min(dp[length - 1], dp[length - 2])
};
时间:O(n) 空间:O(n)
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
dp = [0]*(len(cost))
dp[0] = cost[0]
dp[1] = cost[1]
if len(cost) == 2:
return min(cost)
for i in range(2, len(cost)):
dp[i] = min(dp[i-1]+cost[i],dp[i-2]+cost[i])
return min(dp[-1],dp[-2])
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
n = len(cost)
dp = [0] * (n + 1)
for i in range(2, n + 1):
dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2])
return dp[n]
DP。临界条件是minCosts[0] = 0, minCosts[1] = 0
。状态转移方程是minCosts[i] = min(minCosts[i - 2] + cost[i - 2], minCosts[i - 1] + cost[i - 1])
,即上到Step i的花费为从Step(i - 2)上两步的花费和从Step(i - 1)上一步的花费的最小值。
class Solution {
public int minCostClimbingStairs(int[] cost) {
int n = cost.length;
// Use an array of size n + 1 to store the minimum costs
int[] minCosts = new int[n + 1];
// Base cases: we can either start from index 0 or index 1, no costs for these
minCosts[0] = 0;
minCosts[1] = 0;
for (int i = 2; i < n + 1; i++) {
// minimum cost at step i is the smaller one of the cost climing 2 steps from step (i - 2) and the cost climing 1 step from step (i - 1)
minCosts[i] = Math.min(minCosts[i - 2] + cost[i - 2], minCosts[i - 1] + cost[i - 1]);
}
return minCosts[n];
}
}
复杂度分析
It's DP time! (say it as if you are saying it's morphin time)
压缩一下维度可以让空间更小!
Java:
class Solution {
public int minCostClimbingStairs(int[] cost) {
int dp[] = new int[2];
for (int i = 2; i <cost.length + 1; i++){
int temp = dp[0];
dp[0] = Math.min(dp[0] + cost[i - 1], dp[1] + cost[i - 2]);
dp[1] = temp;
}
return dp[0];
}
}
SC: O(1) TC: O(n)
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
i = len(cost)
dp = [0] * (i + 1)
dp[0] = 0
dp[1] = 0
for j in range(2, i + 1):
dp[j] = min(dp[j-1] + cost[j-1], dp[j-2] + cost[j-2])
return dp[-1]
minCost[i] = min(minCost[i-1] + cost[i], minCost[i-2] + cost[i-1])。
台阶的数组从0开始计数。可以用-1代表地面,并设cost[-1] = 0。
最小总花费的初始值为:
第0级台阶: minCost[0] = min(cost[-1], cost[0]) = min(0, cost[0]) = 0,
第1级台阶: minCost[1] = min(cost[0], cost[1])
作者:armeria-program 链接:https://leetcode-cn.com/problems/min-cost-climbing-stairs/solution/yi-bu-yi-bu-tui-dao-dong-tai-gui-hua-de-duo-chong-/
class Solution {
public int minCostClimbingStairs(int[] cost) {
// int[] res = new int[cost.length];
// res[0] = 0;
// res[1] = Math.min(cost[0], cost[1]);
// for (int i = 2; i < cost.length; i++) {
// res[i] = Math.min(res[i - 1] + cost[i], res[i - 2] + cost[i - 1]);
// }
// return res[res.length - 1];
int res0 = 0;
int res1 = Math.min(cost[0], cost[1]);
int res = 0;
for (int i = 2; i < cost.length; i++) {
res = Math.min(res1 + cost[i], res0 + cost[i- 1]);
res0 = res1;
res1 = res;
}
return res1;
}
}
class Solution(object):
def minCostClimbingStairs(self, cost):
"""
:type cost: List[int]
:rtype: int
"""
dp=[0]*(len(cost)+1)
dp[0],dp[1]=cost[0],cost[1]
for i in range(2,len(cost)+1):
if i!=len(cost):
dp[i] = min(dp[i-1],dp[i-2]) + cost[i]
else:
dp[i] = min(dp[i-1],dp[i-2])
return dp[-1]
时间复杂度:O(N) 空间复杂度:O(N)
DP approach\
define dp function minCost[i] means the minimum cost when reach to ith steps. It can be accomplished from two approaches:\
approach 1. from i - 1
th step, minCost[i - 1] + cost[i]\
approach 2. from i - 2
th step, minCost[i - 2] + cost[i]\
Then minCost[i] = min(approach 1, approach 2)
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
n = len(cost)
minCost = [0] * n
minCost[0] = cost[0]
minCost[1] = cost[1]
if len(cost) == 2:
return min(cost)
for i in range(2, len(cost)):
minCost[i] = min(minCost[i-1] + cost[i], minCost[i-2] + cost[i])
return min(minCost[-1], minCost[-2])
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
n = len(cost)
dp_cost = [0]*(n+1)
for i in range(2,n+1):
t1 = dp_cost[i-1] + cost[i-1]
t2 = dp_cost[i-2] + cost[i-2]
dp_cost[i] = min(t1, t2)
return dp_cost[-1]
Time: O(N)
Space: O(N)
数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始)。
每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯。
请你找出达到楼层顶部的最低花费。在开始时,你可以选择从下标为 0 或 1 的元素作为初始阶梯。
这一题的核心是每一步都有越级和不越级的两种选择,然后要达到最后总体力值消耗最少的结果,很容易联想到使用动态规划,列出状态转移方程即可。
这题题意要审清,选择 cost[0] 作为初始阶梯,是指我人还在地面上,要付出cost[0]的体力值,才能到0号阶梯顶部,也就是登上0号阶梯
选择cost[1]作为初始阶梯,是指我人就踩在0号阶梯上,也就是在0号阶梯的顶部,要再付出cost[1]的体力值才能登上1号阶梯
要登上i号阶梯,怎么花最少的体力呢?
有两种情况,第一种是先花最少的体力登上i - 1号阶梯,再花cost[i]登上i号阶梯 minTotalCost[i - 1] + cost[i]
第二种是想花最少体力登上 i - 2 号阶梯,再花 cost[i - 1] 的体力越级直接登上i号阶梯 minTotalCost[ i - 2] + cost[i - 1]
minTotalCost[i] 指登上i号阶梯一共需要的最少体力值,取上述两种情况中更小的一个
minTotalCost[i] = min{minTotalCost[i - 1] + cost[i] , minTotalCost[ i - 2] + cost[i - 1]}
我们再找出minTotalCost[0]和minTotalCost[1]的值,然后就可以从2开始不断往后递推
minTotalCost[0] ,即登上 0 号台阶需要花的最少总体力值,要么从地面出发 付出cost[0],要么直接站在0号台阶顶部,花费0
所以minTotalCost[0] = min{cost[0] , 0} = 0
minTotalCost[1] 要么从地面出发,付出cost[0]后越级直接登上1号台阶,要么从0号台阶(顶部)出发,付出cost[1]后直接到达1号台阶
所以minTotalCost[1] = min{cost[1] , cost[2]}
class Solution {
public int minCostClimbingStairs(int[] cost) {
/**
这一题的核心是每一步都有越级和不越级的两种选择,然后要达到最后总体力值消耗最少的结果,很容易联想到使用动态规划,列出状态转移方程即可。
这题题意要审清,选择 cost[0] 作为初始阶梯,是指我人还在地面上,要付出cost[0]的体力值,才能到0号阶梯顶部,也就是登上0号阶梯
选择cost[1]作为初始阶梯,是指我人就踩在0号阶梯上,也就是在0号阶梯的顶部,要再付出cost[1]的体力值才能登上1号阶梯
要登上i号阶梯,怎么花最少的体力呢?
有两种情况,第一种是先花最少的体力登上i - 1号阶梯,再花cost[i]登上i号阶梯 minTotalCost[i - 1] + cost[i]
第二种是想花最少体力登上 i - 2 号阶梯,再花 cost[i - 1] 的体力越级直接登上i号阶梯 minTotalCost[i - 2] + cost[i - 1]
minTotalCost[i] 指登上i号阶梯一共需要的最少体力值,取上述两种情况中更小的一个
minTotalCost[i] = min{minTotalCost[i - 1] + cost[i] , minTotalCost[ i - 2] + cost[i - 1]}
我们再找出minTotalCost[0]和minTotalCost[1]的值,然后就可以从2开始不断往后递推
minTotalCost[0] ,即登上 0 号台阶需要花的最少总体力值,要么从地面出发 付出cost[0],要么直接站在0号台阶顶部,花费0
所以minTotalCost[0] = min{cost[0] , 0} = 0
minTotalCost[1] 要么从地面出发,付出cost[0]后越级直接登上1号台阶,要么从0号台阶(顶部)出发,付出cost[1]后直接到达1号台阶
所以minTotalCost[1] = min{cost[1] , cost[2]}
*/
//解法一
//楼梯个数
int size = cost.length;
//创建最小总花费数组
int[] minTotalCost = new int[size];
minTotalCost[0] = 0;
minTotalCost[1] = Math.min(cost[0],cost[1]);//题目说了cost 的长度范围是 [2, 1000]
for(int i = 2; i < size; i++){
minTotalCost[i] = Math.min(minTotalCost[i-1] + cost[i] , minTotalCost[i-2] + cost[i-1]);
}
return minTotalCost[size - 1];
}
}
时间复杂度:$O(n)$
空间复杂度:$O(n)$
在思路一的基础上优化代码,我们目前借助了一个辅助数组minTotalCost[] ,空间复杂度为O(n),这个可以优化
注意到状态转移方程的每一步都只涉及三个变量,我们可以去掉数组,只维护这三个变量,并不断更新,效果是一样的
class Solution {
public int minCostClimbingStairs(int[] cost) {
//解法二
//在解法一的基础上优化代码
//楼梯个数
int size = cost.length;
int minTotalCost0 = 0; //minTotalCost[0] = 0;
int minTotalCost1 = Math.min(cost[0],cost[1]); //minTotalCost[1] = Math.min(cost[0],cost[1])
//需要的答案
//debug: 注意这里不能写成minTotalCost2 = 0,初值一定要和minTotalCost1相等
//否则,如果就只有两个楼梯,底下的for循环是直接跳过的,那么你的最小总花费岂不是0了,这就不行
int minTotalCost2 = minTotalCost1;
for(int i = 2; i < size; i++){
minTotalCost2 = Math.min(minTotalCost1 + cost[i] , minTotalCost0 + cost[i-1]);
minTotalCost0 = minTotalCost1;
minTotalCost1 = minTotalCost2;
}
return minTotalCost2;
}
}
时间复杂度:$O(n)$
空间复杂度:$O(1)$
title: "Day 54 746. 使用最小花费爬楼梯" date: 2021-11-02T12:23:08+08:00 tags: ["Leetcode", "c++", "DP"] categories: ["91-day-algorithm"] draft: true
数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始)。
每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯。
请你找出达到楼层顶部的最低花费。在开始时,你可以选择从下标为 0 或 1 的元素作为初始阶梯。
示例 1:
输入:cost = [10, 15, 20]
输出:15
解释:最低花费是从 cost[1] 开始,然后走两步即可到阶梯顶,一共花费 15 。
示例 2:
输入:cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
输出:6
解释:最低花费方式是从 cost[0] 开始,逐个经过那些 1 ,跳过 cost[3] ,一共花费 6 。
提示:
cost 的长度范围是 [2, 1000]。
cost[i] 将会是一个整型数据,范围为 [0, 999] 。
- 1、跟斐波那契是一样的动态规划题目,由于有爬一层跟爬两层的选择,所以只需要返回数组最后两个值中较小的那一个即可。
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int n = cost.size();
int dp[2];
dp[0] = cost[0];
dp[1] = cost[1];
for(int i = 2; i < n; i++)
{
int mix = min(dp[0], dp[1]) + cost[i];
dp[0] = dp[1];
dp[1] = mix;
}
return min(dp[0], dp[1]);
}
};
时间复杂度:O(n)
空间复杂度:O(1)
var minCostClimbingStairs = function(cost) {
if(cost===null||cost.length==0){
return 0;
}
const dp=[];
dp[0]=cost[0];
dp[1]=cost[1];
for(let i=2;i<=cost.length;i++){
dp[i]=Math.min(dp[i-2],dp[i-1])+ (i == cost.length ? 0 : cost[i]);
}
return dp[cost.length]
};
DP
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
n = len(cost)
dp = [0] * 3
dp[0], dp[1] = cost[0], cost[1]
for i in range(2, n+1):
if i == n:
dp[-1] = min(dp[0], dp[1])
else:
dp[-1] = min(dp[0], dp[1]) + cost[i]
dp[0] = dp[1]
dp[1] = dp[2]
return dp[-1]
Space: O(1) Time: O(n)
https://leetcode-cn.com/problems/min-cost-climbing-stairs/
DP, 到达当前台阶i花费最小dp[i],或到达i-1最小花费dp[i-1],那么minCost [i] = min(dp[i], dp[i - 1]).
class Solution {
public int minCostClimbingStairs(int[] cost) {
int f1 = 0;
int f2 = 0;
for(int i = cost.length - 1; i >= 0; i--) {
int f0 = cost[i] + Math.min(f1, f2);
f2 = f1;
f1 = f0;
}
return Math.min(f1, f2);
}
}
O(n)
O(1)
todo
定义好状态方程,初始化dp值,用dp方程
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
# state dp[i] 代表到第i个台阶所用的最小的cost
n = len(cost)
dp = [0] * n
# initialize
dp[0] = cost[0]
dp[1] = cost[1]
# function
for i in range(2, n):
dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i]
return min(dp[n - 1], dp[n -2])
时间复杂度:O(n) 空间复杂度:O(n)
https://leetcode.com/problems/min-cost-climbing-stairs/
爬到顶的cost是由倒数第一步的最小cost和倒数第二步的最小cost决定。
class Solution {
public int minCostClimbingStairs(int[] cost) {
if (cost.length < 2) {
return cost[0];
}
int[] dp = new int[cost.length];
dp[0] = cost[0];
dp[1] = cost[1];
for (int i = 2; i < cost.length; i++) {
dp[i] = Math.min(dp[i - 1] + cost[i], dp[i - 2] + cost[i]);
}
return Math.min(dp[cost.length - 1], dp[cost.length - 2]);
}
}
时间:O(n)
空间:O(n)
动态规划
class Solution {
public int minCostClimbingStairs(int[] cost) {
int n = cost.length;
int[] dp = new int[n + 1];
dp[0] = dp[1] = 0;
for (int i = 2; i <= n; i++) {
dp[i] = Math.min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
}
return dp[n];
}
}
时间复杂度:O(n) 空间复杂度:O(n)
class Solution(object):
def minCostClimbingStairs(self, cost):
dp = [0 for _ in range(len(cost) + 1)]
for i in range(len(cost) + 1):
if i == 0:
dp[i] = 0
elif i == 1:
dp[i] = 0
else:
dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2])
return dp[-1]
T: O(N) S: O(N)
var minCostClimbingStairs = function (cost) {
const dp = [cost[0], cost[1]];
for (let i = 2; i < cost.length; ++i) {
dp[i] = Math.min(dp[i - 1] + cost[i], dp[i - 2] + cost[i]);
}
return Math.min(dp[cost.length - 1], dp[cost.length - 2]);
};
主要的思想为使用动态规划来完成,能够爬到某一层楼梯最小花费等价与爬到前二层加上他们当层的代价的最小值,于是状态转移方程就变成了 dp[i] = Math.min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);又因为这是和前两个的状态有关的,所有可以只使用二个变量来存储,这样空间复杂度就降为了O(1)。
class Solution { public int minCostClimbingStairs(int[] cost) { int n=cost.length; int cout=0; int prev = 0, curr = 0; for(int i=2;i<=n;i++){ int next = Math.min(curr + cost[i - 1], prev + cost[i - 2]); prev = curr; curr = next; } return curr; } }
时间复杂度:O(n)
空间复杂度:O(1)
思路: 动态规划,dp[n] = min(dp[n - 1) + cost[n - 1], dp[n - 2] + cost[n - 2]), 使用两个变量记录dp[n - 1]和dp[n - 2]的值,初始值dp[0] = dp[1] = 0
复杂度分析:
代码(C++):
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
int n = cost.size();
int dp1 = 0, dp2 = 0;
for (int i = 2; i <= n; ++i) {
int tmp = min(dp1 + cost[i - 1], dp2 + cost[i - 2]);
dp2 = dp1;
dp1 = tmp;
}
return dp1 ;
}
};
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
vector<int> cache(cost.size());
return min(help(cost, 0, cache), help(cost, 1, cache));
}
int help(vector<int>& cost, int index, vector<int>& cache){
if(index >= cost.size()) return 0; //到达递归末尾
if(cache[index]) return cache[index]; //如果该点已经计算过,不再计算
int take1step = help(cost, index + 1, cache);
int take2step = help(cost, index + 2, cache);
cache[index] = min(take1step, take2step) + cost[index];
return cache[index];
}
};
dp + 滚动数组记录 dp 方程 dp[i] = cost[i] + min(dp[i - 1], dp[i - 2]).
class Solution {
public int minCostClimbingStairs(int[] cost) {
if (cost.length == 1) {
return cost[0];
}
if (cost.length == 2) {
return Math.min(cost[0], cost[1]);
}
int[] dp = new int[3];
dp[0] = cost[0];
dp[1] = cost[1];
for (int i = 2; i < cost.length; i++) {
dp[i % 3] = cost[i] + Math.min(dp[(i - 1) % 3], dp[(i - 2) % 3]);
}
return Math.min(dp[(cost.length - 1) % 3], dp[(cost.length - 2) % 3]);
}
}
复杂度分析 时间复杂度:O(n) 空间复杂度:O(n)
思路: maintain a array for the minimum cost to reach to each step
class Solution {
public int minCostClimbingStairs(int[] cost) {
int[] dp = new int[cost.length+1]; // dp[i] is the minimum cost to reach ith step
dp[0] = 0;
dp[1] = 0;
for (int i = 2; i <= cost.length; i++) {
dp[i] = Math.min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2]);
}
return dp[cost.length];
}
}
Time Complexity: O(n) Space Complexity: O(1)
class Solution {
public int minCostClimbingStairs(int[] cost) {
if (cost == null || cost.length == 0)
return 0;
int[] dp = new int[cost.length + 1];
dp[0] = cost[0];
dp[1] = cost[1];
for(int i = 2; i <= cost.length; i++)
dp[i] = Math.min(dp[i - 1], dp[i - 2]) + (i == cost.length ? 0 : cost[i]);
return dp[cost.length];
}
}
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
dp = [0] * (len(cost)+1)
dp[0], dp[1] = cost[0], cost[1]
for i in range(2, len(cost)+1):
dp[i] = min(dp[i-1], dp[i-2]) + (cost[i] if i != len(cost) else 0)
return dp[-1]
TC:O(N) SC:O(N)
假设数组 cost 的长度为 n,则 n 个阶梯分别对应下标 0 到 n−1,楼层顶部对应下标 n,问题等价于计算达到下标 n 的最小花费。可以通过动态规划求解。
创建长度为 n+1 的数组 dp,其中dp[i] 表示达到下标 ii 的最小花费。
由于可以选择下标 0 或 1 作为初始阶梯,因此有dp[0]=dp[1]=0。
依次计算 dp 中的每一项的值,最终得到的 dp[n] 即为达到楼层顶部的最小花费。
class Solution {
public int minCostClimbingStairs(int[] cost) {
int n = cost.length;
int[] dp = new int[n+1];
dp[0] = dp[1] = 0;
for(int i = 2;i<=n;i++){
dp[i] = Math.min(cost[i-1] + dp[i-1] , cost[i-2] + dp[i-2]);
}
return dp[n];
}
}
时间复杂度:O(n)
空间复杂度:O(n)
数组
,动态规划
思路: 动态规划,dp[n] = min(dp[n - 1) + cost[n - 1], dp[n - 2] + cost[n - 2]), 使用两个变量记录dp[n - 1]和dp[n - 2]的值,初始值dp[0] = dp[1] = 0
复杂度分析:
时间复杂度: O(N), N为楼梯层数 空间复杂度: O(1) 代码(C++):
class Solution {
public:
int minCostClimbingStairs(vector
for (int i = 2; i <= n; ++i) {
int tmp = min(dp1 + cost[i - 1], dp2 + cost[i - 2]);
dp2 = dp1;
dp1 = tmp;
}
return dp1 ;
}
};
class Solution {
public int minCostClimbingStairs(int[] cost) {
if (cost == null || cost.length == 0)
return 0;
int[] dp = new int[cost.length + 1];
dp[0] = cost[0];
dp[1] = cost[1];
for(int i = 2; i <= cost.length; i++)
dp[i] = Math.min(dp[i - 1], dp[i - 2]) + (i == cost.length ? 0 : cost[i]);
return dp[cost.length];
}
}
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
dp=[float('inf')]*(len(cost)+1)
dp[0]=0
dp[1]=0
for i in range(2,len(cost)+1):
dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2])
return dp[len(cost)]
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
memo = {}
def dfs(cur_stair):
if cur_stair >= len(cost):
return 0
cur_cost = 0 if cur_stair == -1 else cost[cur_stair]
if cur_stair+1 in memo:
cost1 = memo[cur_stair+1]
else:
cost1 = dfs(cur_stair+1)
if cur_stair+2 in memo:
cost2 = memo[cur_stair+2]
else:
cost2 = dfs(cur_stair+2)
memo[cur_stair] = cur_cost+ min(cost1, cost2)
return memo[cur_stair]
return dfs(-1)
Time: O(n)
Space: O(n)
使用动态规划,用数组记录min cost,手动设置0和1级初始阶梯,将当前层的min cost设置为前1级和前2级中最小的min cost + cost[i],返回数组中最后一位为最小cost。
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
cost.append(0)
minCost = []
minCost.append(cost[0])
minCost.append(cost[1])
for i in range(2, len(cost)):
minCost.append(min(minCost[i-2], minCost[i-1]) + cost[i])
return minCost[-1]
时间:O(n) 空间:O(n)
https://leetcode-cn.com/problems/min-cost-climbing-stairs/
DP
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
# dp[i]代表到达位置i的最小体力花费
# dp[i] = min(dp[i - 1] + cost[i], dp[i - 2] + cost[i])
n = len(cost)
# 由于可以选择下标 0 或 1 作为初始阶梯,因此有 dp[0] = dp[1] = 0
dp = [0 for _ in range(n + 1)]
for i in range(2, n + 1):
dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2])
return dp[n]
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
# dp[i]代表到达位置i的最小体力花费
# dp[i] = min(dp[i - 1] + cost[i], dp[i - 2] + cost[i])
n = len(cost)
prev = cur = 0
for i in range(2, n + 1):
nxt = min(cur + cost[i - 1], prev + cost[i - 2])
prev, cur = cur, nxt
return nxt
动态规划 or 递归
int minCostClimingStairs2(vector<int>& cost) {
int n = cost.size();
int dp[n+1];
dp[0] = dp[1] = 0;
for (int i = 2; i < n + 1; ++i) {
dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2]);
}
return dp[n];
}
int minCostClimingStairs(vector<int>& cost, int n) {
if (n == 0 || n == 1) {
return 0;
}
return min(minCostClimingStairs(cost, n-1) + cost[n-1], minCostClimingStairs(cost, n-2) + cost[n-2]);
}
思路 dp[i] = min(dp[i-1]+cost[i-1],p[i-2]+cost[i-2])
代码 func minCostClimbingStairs(cost []int) int { dp :=make([]int,len(cost)+1) dp[0] = 0 dp[1] = 0 for i:=2;i<len(dp);i++ { if dp[i-1]+cost[i-1]>dp[i-2]+cost[i-2] { dp[i]= dp[i-2]+cost[i-2] }else{ dp[i]= dp[i-1]+cost[i-1] } } return dp[len(cost)] } 复杂度分析 时间复杂度:O(n) 空间复杂度:O(n)
class Solution2:
def minCostClimbingStairs(self, cost: List[int]) -> int:
a,b = cost[0],cost[1]
for i in range(2,(len(cost)+1)):
c = min(a, b) + (cost[i] if i !=len(cost) else 0)
a = b
b = c
return c
dp1表示退一步的最小cost,dp2表示退两步的最小cost,每次取最小的cost+当前的cost。
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
n = len(cost)
dp = [0]*n
dp1 = cost[0]
dp2 = cost[1]
for i in range(2,n):
dp1,dp2 = dp2,min(dp1,dp2)+cost[i]
return min(dp1,dp2)
复杂度分析
思路
dp
代码
class Solution {
public int minCostClimbingStairs(int[] cost) {
if (cost == null || cost.length == 0){
return 0;
}
int dp[] = new int[cost.length + 1];
dp[0] = cost[0];
dp[1] = cost[1];
for (int i = 2; i <= cost.length; i++) {
if (i == cost.length) {
dp[i] = Math.min(dp[i - 1], dp[i - 2]);
} else{
dp[i] = cost[i] + Math.min(dp[i - 1], dp[i - 2]);
}
}
return dp[cost.length];
}
}
复杂度
时间复杂度:O(N)
空间复杂度:O(N)
/**
* @param {number[]} cost
* @return {number}
*/
const minCostClimbingStairs = function(cost) {
let twoStepBefore = cost[0];
let oneStepBefore = cost[1];
let curr = 0;
for (let i = 2; i < cost.length; i++) {
curr = Math.min(twoStepBefore, oneStepBefore) + cost[i];
twoStepBefore = oneStepBefore;
oneStepBefore = curr;
}
return Math.min(twoStepBefore, oneStepBefore);
};
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
for i in range(2, len(cost)):
cost[i] += min(cost[i - 1], cost[i - 2])
return min(cost[-2], cost[-1])
dp,可以从0或者1的位置开始都可以,所以0和1的memo值都为0。从index3开始,memo记录下从这一格往后走的cost是多少,即为前一格的memo值加上他的cost和前两格的memo值加上他的cost取最小值(either从前一格来或者从前两格来)。最后一个就是答案,因为我们initialize的是size + 1,就是到top的步数。
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
vector<int> memo(cost.size() + 1, 0);
for (int i = 2; i < cost.size() + 1; ++i) {
memo[i] = min(memo[i - 1] + cost[i - 1], memo[i - 2] + cost[i - 2]);
}
return memo.back();
}
};
动态规划问题
定义数组dp,dp[i]代表爬到第i级阶梯的最小花费,有题目可知dp[0]=dp[1]=0;
爬到第i级所需花费=爬到第(i-1)级阶梯的最小花费+第(i-1)级阶梯的花费/爬到第(i-2)级阶梯的最小花费+第(i-2)级阶梯的花费
取二者中的最小值,即:
dp[i]=Math.min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2])
Java Code:
class Solution {
//注意:要准确理解题意,观察用例
//思路:动态规划
public int minCostClimbingStairs(int[] cost) {
int n=cost.length;
int[] dp=new int[n+1];//dp[i]代表到达第i级阶梯的最小花费
dp[0]=0;
dp[1]=0;
for(int i=2;i<=n;i++){
dp[i]=Math.min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
}
return dp[n];
}
}
复杂度分析
令 n 为数组长度。
var minCostClimbingStairs = function(cost) {
let p=q=0,temp;
for(let i=2;i<=cost.length;i++){
temp = q
q=Math.min(p+cost[i-2],q+cost[i-1]);
p = temp;
}
return q;
};
746.使用最小花费爬楼梯
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/min-cost-climbing-stairs/
前置知识
题目描述
每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯。
请你找出达到楼层顶部的最低花费。在开始时,你可以选择从下标为 0 或 1 的元素作为初始阶梯。
示例 1:
输入:cost = [10, 15, 20] 输出:15 解释:最低花费是从 cost[1] 开始,然后走两步即可到阶梯顶,一共花费 15 。 示例 2:
输入:cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] 输出:6 解释:最低花费方式是从 cost[0] 开始,逐个经过那些 1 ,跳过 cost[3] ,一共花费 6 。
提示:
cost 的长度范围是 [2, 1000]。 cost[i] 将会是一个整型数据,范围为 [0, 999] 。