746. 使用最小花费爬楼梯


官方链接

https://leetcode-cn.com/problems/min-cost-climbing-stairs/

数组的每个索引作为一个阶梯,第 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。

注意:

  1. cost 的长度将会在 [2, 1000]
  2. 每一个 cost[i] 将会是一个 Integer 类型,范围为 [0, 999]

思路

递归 + 记忆化搜索

时间复杂度 O(n)
空间复杂度 O(n)

dp[i] := min cost to climb to n-th step
dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2])
ans = dp(n)

dp

时间复杂度 O(n)
空间复杂度 O(n) --> O(1)

dp[i] := min cost brfore leaving n-th step
dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i]
ans = min(dp[i - 1], dp[i - 2])

解法一

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        Map<Integer, Integer> mem = new HashMap<>();
        return helper(mem, cost, cost.length);
    }

    private int helper(Map<Integer, Integer> mem, int[] cost, int i) {
        if (i <= 1) return 0;
        if (mem.containsKey(i)) return mem.get(i);
        int a = Math.min(helper(mem, cost, i - 1) + cost[i - 1], helper(mem, cost, i - 2) + cost[i - 2]);
        mem.put(i, a);
        return a;
    }
}

解法二

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        Map<Integer, Integer> mem = new HashMap<>();
        return Math.min(helper(mem, cost, cost.length - 1), helper(mem, cost, cost.length - 2));
    }

    private int helper(Map<Integer, Integer> mem, int[] cost, int i) {
        if (i < 0) return 0;
        if (mem.containsKey(i)) return mem.get(i);
        int a = Math.min(helper(mem, cost, i - 1), helper(mem, cost, i - 2)) + cost[i];
        mem.put(i, a);
        return a;
    }
}

解法三

改为顺推

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int n = cost.length;
        int[] dp = new int[n];
        dp[0] = cost[0];
        dp[1] = cost[1];

        for (int i = 2; i < n; i++) {
            dp[i] = Math.min(dp[i - 1], dp[i - 2]) + cost[i];
        }
        return Math.min(dp[n - 1], dp[n - 2]);
    }
}
class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int n = cost.length;
        int[] dp = new int[n + 1];
        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];
    }
}

O(1)

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int n = cost.length;
        int dp1 = 0, dp2 = 0;

        for (int i = 2; i <= n; i++) {
            int dp = Math.min(dp1 + cost[i - 1], dp2 + cost[i - 2]);
            dp2 = dp1;
            dp1 = dp;
        }
        return dp1;
    }
}