leetcode:使用最小花费爬楼梯

题目来源:力扣

题目介绍:

数组的每个索引做为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 costi
每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯或者爬两个阶梯。
您需要找到达到楼层顶部的最低花费。在开始时,你可以选择从索引为 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] 将会是一个Integer类型,范围为 [0, 999]。
=======================================================

审题:

该题目是一道较简单的动态规划类问题, 但由于一开始没有选好状态变量,导致想了好一会而.

首先, 对于该爬楼梯问题,我们可以选择剩余第一个楼梯级数作为状态变量, 我们可以选择登上该级楼梯, 也可以选择不登上该级楼梯, 由于是否登上当前阶梯决定是我们是否需要登上下一级楼梯, 因此我们添加一个额外的状态变量表示是否登上当前楼梯. 我们使用S[i][0]表示当前剩余第一个楼梯为i级时, 登上该楼梯的最小花费, S[i][1]表示如果不登上当前楼梯的最小花费. 如果我们没有踏上当前楼梯, 则我们只能踏上下一级楼梯(最多一次跨上两级).则我们可以得到如下状态转移方程:
S[i][0]=cost[i]+min{S[i+1][0],S[i+1][1]}S[i][0] = cost[i] + min\{S[i+1][0], S[i+1][1]\}
S[i][1]=S[i+1][0]S[i][1] = S[i+1][0]

实际上, 由于当前的选择为二元选择, 我们可以简化当前最优子结构.对于该爬楼梯问题, 我们选择剩余第一个楼梯级数作为状态变量,在我们登上该级楼梯后, 我们可以选择跨一步登上下一级级楼梯, 也可以选择跨两步登上下下一级楼梯. 我们使用S[i]表示当前剩余第一个楼梯为i级时, 我们登上第i级楼梯的最少花费. 此时我们可以得到如下状态转移方程:
S[i]=cost[i]+min{S[i+1],S[i+2]}S[i] = cost[i] + min\{S[i+1], S[i+2]\}.
此时的basecase为S[cost.length1]=cost[cost.length1]S[cost.length-1] = cost[cost.length-1],
S[cost.length2]=cost[cost.length2]S[cost.length-2] = cost[cost.length-2];

代码实现如下:

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int[] S = new int[cost.length];
        //basecase
        S[cost.length-1] = cost[cost.length-1]; 
        S[cost.length-2] = cost[cost.length-2];`在这里插入代码片`
        
        for(int i = cost.length-3; i >= 0; i--){
            S[i] = cost[i] + Math.min(S[i+1], S[i+2]);
        }

        return Math.min(S[0], S[1]);
    }
}

由于当前状态仅有其后续的两个状态相关, 因此, 我们可以考虑进行状态压缩, 将空间复杂度由O(N)降低到O(1)

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int[] S = new int[3];
        S[(cost.length-2) % 3] = cost[cost.length-2];
        S[(cost.length-1) % 3] = cost[cost.length-1];

        for(int i = cost.length-3; i >= 0; i--){
            S[i % 3] = cost[i] + Math.min(S[(i+1) % 3], S[(i+2) % 3]);
        }

        return Math.min(S[0], S[1]);
    }
}

如果原数组允许改变, 我们可以直接更改原数组, 而无需使用额外空间.

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        for(int i = cost.length-3; i >= 0; i--){
            cost[i] = cost[i] + Math.min(cost[i+1], cost[i+2]);
        }
        return Math.min(cost[0], cost[1]);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章