The sword refers to offer88: the least cost of climbing stairs

Question:
Each subscript of the array is used as a step, and the i-th step corresponds to a non-negative physical cost value cost[i] (the subscript starts from 0).
Every time you climb a ladder, you will spend the corresponding stamina value. Once you have paid the corresponding stamina value, you can choose to climb one ladder or two ladders.
Please find the minimum cost to reach the top of the floor. At the beginning, you can choose the element from index 0 or 1 as the initial ladder.
1.
Input: cost = [10, 15, 20]
Output: 15
Explanation: The minimum cost starts from cost[1], and then takes two steps to the top of the ladder, which costs 15 in total.
2.
Input: cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
Output: 6
Explanation: The lowest cost method is to start from cost[0], go through those 1s one by one, skip cost[3] , which costs 6 in total.
Analysis:
Each time you climb this question, you can either climb up one step or two steps, which means that there are two choices for each step. It seems that this is related to backtracking, but the problem is not to find out how many ways to climb the stairs, but to calculate the minimum cost of climbing the stairs, i.e. to calculate the optimal solution to the problem, so this problem is more suitable for dynamic programming .
For the dynamic programming method, we must first determine the state transition equation, which can be expressed as f(i) to represent the minimum cost of climbing from the i-th step of the stairs. If a stair has n steps (steps from 0 to n-1), since 1 or 2 steps can be climbed at a time, it is possible to climb from the n-2 or n-1 steps to The top of the stairs, the minimum of f(n-1) and f(n-2), is the optimal solution to this problem. The minimum cost of climbing from the i-th step should be the lesser of the minimum cost of climbing from the i-1st step and the minimum cost of climbing from the i-2th step plus the The cost of i steps = "f(i)=min(f(i-1),f(i-2))+cos[i]. This equation has an implicit condition, that is, i is greater than or equal to 2. If i is equal to 0, you can climb directly from the 0th step. f(0)=cos[0], if i is equal to 1, it is mentioned in the title that you can climb up from the first step, so f(1)=cos[1].
There are four solutions to this problem:
circle 9 represents f(9). The first solution seems to have a simple code, but the time complexity is very bad. For example, f(6) needs to be calculated many times. In fact, only one calculation is enough. Other The calculations are redundant, so we need a pruning operation, which is the second solution, to avoid repeated calculations and use an array to store the results.
Or we can solve this process from the bottom up in a different way, that is, start with the sub-problems, and find the result of f(i) based on the solutions of the two sub-problems f(i-1) and f(i-2). The fourth idea is to optimize on the basis of the third idea, mainly to reduce the space complexity. In the front, an array of length n is used to save all the results of f(i) and solve the problem of f(i). The results are saved. However, when solving f(i), only the results of f(i-1) and f(i-2) are needed. The results from 0 to f(i-3) have no effect on solving f(i), so only All you need is an array of length 2, see the code for details.
insert image description here

Code:

import java.util.Map;

public class MinCostClimbingStairs {
    
    
    public static void main(String[] args) {
    
    
        MinCostClimbingStairs minCostClimbingStairs = new MinCostClimbingStairs();
        int[] cost = {
    
    1,100,1,1,100,1};
        int i = minCostClimbingStairs.minCostClimbingStairs3(cost);
        System.out.println(i);
    }
    public int minCostClimbingStairs(int[] cost){
    
    
        int len = cost.length;
        return Math.min(helper1(cost,len-2),helper1(cost,len-1));
    }

    private int helper1(int[] cost, int i) {
    
    
        if (i<2){
    
    
            return cost[i];
        }
        return Math.min(helper1(cost,i-1),helper1(cost,i-2))+cost[i];
    }
//利用数组来存储结果
    public int minCostClimbingStairs1(int[] cost) {
    
    
        int len = cost.length;//该数组的每个元素都初始化为0
        int[] dp = new int[len];
        helper(cost,len-1,dp);
        return Math.min(dp[len - 2],dp[len - 1]);
    }

    private void helper(int[] cost, int i, int[] dp) {
    
    
        if (i < 2){
    
    
            dp[i] = cost[i];
            //由于每级台阶往上爬的成本都是正数,因此如果某个问题f(i)之前已经求解过了,那么一定是一个大于0的数值。
        }else if (dp[i] == 0){
    
    
            helper(cost,i-2,dp);
            helper(cost,i-1,dp);
            dp[i] = Math.min(dp[i-2],dp[i-1])+cost[i];
        }
    }
//    自下而上,这个思路感觉要比自上而下的思路更好想
    public int minCostClimbingStairs2(int[] cost){
    
    
        int len = cost.length;
        int[] dp = new int[len];
        dp[0] = cost[0];
        dp[1] = cost[1];
        for (int i = 2; i < len; i++) {
    
    
            dp[i] = Math.min(dp[i-1],dp[i-2])+cost[i];
        }
        return Math.min(dp[len-2],dp[len-1]);
    }
    //优化空间复杂度解法
    public int minCostClimbingStairs3(int[] cost){
    
    
        int[] dp = new int[]{
    
    cost[0],cost[1]};
        for (int i = 2; i < cost.length; i++) {
    
    
//            用f(i)的结果覆盖f(i-2)的结果并不会带来任何问题
//            dp[0] 从开始到最终分别对应的是下标为0 2 4 6...的数组值,dp[1]同理。
//            求解的f(i)的结果保存在数组下标为“i%2”的位置。
            dp[i%2] = Math.min(dp[0],dp[1]) + cost[i];
        }
        return Math.min(dp[0],dp[1]);
    }
}

insert image description here

Guess you like

Origin blog.csdn.net/Jiaodaqiaobiluo/article/details/122462364