746. Min Cost Climbing Stairs* (使用最小花费爬楼梯)
https://leetcode.com/problems/min-cost-climbing-stairs/
题目描述
You are given an integer array cost
where cost[i]
is the cost of i
th step on a staircase. Once you pay the cost, you can either climb one or two steps.
You can either start from the step with index 0
, or the step with index 1
.
Return the minimum cost to reach the top of the floor.
Example 1:
Example 2:
Constraints:
-
2 <= cost.length <= 1000
-
0 <= cost[i] <= 999
代码实现
我觉得这道题有意思的地方在于, 每次去写它总认为自己会写错. 今天才明白, 之所以会产生这样的想法, 是因为我之前并没有将求解方法纳入现有的思考体系中. 之前在 746. Min Cost Climbing Stairs* 写的状态方程虽然简洁, 但感觉不符合我现在的思考方式.
本题采用动态规划求解, 使用 dp[i]
表示达到 i
时所需要付出的最小代价. 假设 cost
数组的大小为 N
, 最终的目标就是跳到第 N
个位置上, 所付出的代价就是 dp[N]
. 根据题意, 当你位于第 i
个位置时, 付出当前位置的花费 cost[i]
, 就可以跳一步或者两步. 那么要跳到第 i
个位置上时, 要么一开始就位于第 i - 1
的位置上, 然后付出 cost[i - 1]
的代价跳一步到达第 i
个位置; 要么一开始位于第 i - 2
的位置上, 然后付出 cost[i - 2]
的代价跳两步到达第 i
个位置;
综上, 状态转移方程呼之欲出:
要确定初始状态, 题目中说可以从第 0
个位置和第 1
个位置开始起跳, 那么:
再次注意 dp[i]
的含义是到达 i
时所需要付出的最小代价, 该位置上的花费 cost[i]
指的是你要离开 第 i
个位置时需要付出的代价, 由于我们可以直接从第 0
个位置和第 1
个位置开始起跳, 所以它们的初始值均设置为 0
. 最后我们只需要返回 dp[N]
就可以求解, 代码如下:
注意题目中说了数组的大小至少为 2
, 所以 N < 2
的情况不用考虑. 写到这, 代码还不算完, 还需要考虑能否进一步优化. 观察到 dp[i]
的结果只和 dp[i - 1]
和 dp[i - 2]
有关, 似乎不需要使用 vector
来记录所有历史结果, 只需要使用变量 dp0 = dp[i - 2], dp1 = dp[i - 1]
来保留历史状态, 同时不断维护 dp0
和 dp1
的状态.
另外可以看看下面 “类似的题”, 均采用相同的思路就可以求解.
类似的题
- 53. Maximum Subarray*(最大子序和)
- 300. **Longest Increasing Subsequence (最长递增子序列)
- 152. Maximum Product Subarray**(乘积最大子数组)