Given an array of integers cost[] of length n, where cost[i] is the cost of the ith step on a staircase. Once the cost is paid, we can either climb one or two steps. We can either start from the step with index 0, or the step with index 1. The task is to find the minimum cost to reach the top.
Examples:
Input: cost[] = [10, 15, 20] Output: 15 Explanation: The cheapest option is to start from step with index 1, pay cost[1] and go to the top.
Input: cost[] = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] Output: 6 Explanation: The cheapest option is to start from step with index 1on cost[0], and only step on 1s, skipping cost[3].
There are n stairs, and a person is allowed to climb 1 or 2 stairs. If a person is standing at i-th stair, the person can move to i+1, i+2, stair. A recursive function can be formed where at current index i the function is recursively called for i+1, i+2 th stair. There is another way of forming the recursive function. To reach a stair i, a person has to jump either from i-1, or i-2 th stair.
// C++ program to count number of// ways to reach nth stair.#include<bits/stdc++.h>usingnamespacestd;intminCostRecur(inti,vector<int>&cost){// Base caseif(i==0||i==1){returncost[i];}returncost[i]+min(minCostRecur(i-1,cost),minCostRecur(i-2,cost));}intminCostClimbingStairs(vector<int>&cost){intn=cost.size();if(n==1)returncost[0];// Return minimum of cost to // reach (n-1)th stair and // cost to reach (n-2)th stairreturnmin(minCostRecur(n-1,cost),minCostRecur(n-2,cost));}intmain(){vector<int>cost={16,19,10,12,18};cout<<minCostClimbingStairs(cost)<<endl;return0;}
Java
// Java program to count number of// ways to reach nth stair.importjava.util.*;classGfG{staticintminCostRecur(inti,int[]cost){// Base caseif(i==0||i==1){returncost[i];}returncost[i]+Math.min(minCostRecur(i-1,cost),minCostRecur(i-2,cost));}staticintminCostClimbingStairs(int[]cost){intn=cost.length;if(n==1)returncost[0];// Return minimum of cost to // reach (n-1)th stair and // cost to reach (n-2)th stairreturnMath.min(minCostRecur(n-1,cost),minCostRecur(n-2,cost));}publicstaticvoidmain(String[]args){int[]cost={16,19,10,12,18};System.out.println(minCostClimbingStairs(cost));}}
Python
# Python program to count number of # ways to reach nth stair.defminCostRecur(i,cost):# Base caseifi==0ori==1:returncost[i]returncost[i]+min(minCostRecur(i-1,cost),minCostRecur(i-2,cost))defminCostClimbingStairs(cost):n=len(cost)ifn==1:returncost[0]# Return minimum of cost to # reach (n-1)th stair and # cost to reach (n-2)th stairreturnmin(minCostRecur(n-1,cost),minCostRecur(n-2,cost))if__name__=="__main__":cost=[16,19,10,12,18]print(minCostClimbingStairs(cost))
C#
// C# program to count number of// ways to reach nth stair.usingSystem;classGfG{staticintminCostRecur(inti,int[]cost){// Base caseif(i==0||i==1){returncost[i];}returncost[i]+Math.Min(minCostRecur(i-1,cost),minCostRecur(i-2,cost));}staticintminCostClimbingStairs(int[]cost){intn=cost.Length;if(n==1)returncost[0];// Return minimum of cost to reach (n-1)th // stair and cost to reach (n-2)th stairreturnMath.Min(minCostRecur(n-1,cost),minCostRecur(n-2,cost));}staticvoidMain(string[]args){int[]cost={16,19,10,12,18};Console.WriteLine(minCostClimbingStairs(cost));}}
JavaScript
// JavaScript program to count number of// ways to reach nth stair.functionminCostRecur(i,cost){// Base caseif(i===0||i===1){returncost[i];}returncost[i]+Math.min(minCostRecur(i-1,cost),minCostRecur(i-2,cost));}functionminCostClimbingStairs(cost){letn=cost.length;if(n===1)returncost[0];// Return minimum of cost to reach (n-1)th stair and // cost to reach (n-2)th stairreturnMath.min(minCostRecur(n-1,cost),minCostRecur(n-2,cost));}// Driver Codeletcost=[16,19,10,12,18];console.log(minCostClimbingStairs(cost));
Output
31
[Better Approach 1] Using Top-Down DP (Memoization) – O(n) Time and O(n) Space
If we notice carefully, we can observe that the above recursive solution holds the following two properties of Dynamic Programming:
1. Optimal Substructure: Minimum cost to reach the nth stair, i.e., minCost(n), depends on the optimal solutions of the subproblems minCost(n-1) , and minCost(n-2). By choosing the minimum of these optimal substructures, we can efficiently calculate the minimum cost to reach the nth stair.
2. Overlapping Subproblems: While applying a recursive approach in this problem, we notice that certain subproblems are computed multiple times. For example, when calculating minCost(4), we recursively calculate minCost(3) and minCost(2) which in turn will recursively compute minCost(2) again. This redundancy leads to overlapping subproblems.
There is only one parameter that changes in the recursive solution and it can go from 0 to n. So we create a 1D array of size n+1 for memoization.
We initialize this array as -1 to indicate nothing is computed initially.
Now we modify our recursive solution to first check if the value is -1, then only make recursive calls. This way, we avoid re-computations of the same subproblems.
C++
// C++ program to count number of// ways to reach nth stair.#include<bits/stdc++.h>usingnamespacestd;intminCostRecur(inti,vector<int>&cost,vector<int>&memo){// Base caseif(i==0||i==1){returncost[i];}// If value is memoizedif(memo[i]!=-1)returnmemo[i];returnmemo[i]=cost[i]+min(minCostRecur(i-1,cost,memo),minCostRecur(i-2,cost,memo));}intminCostClimbingStairs(vector<int>&cost){intn=cost.size();if(n==1)returncost[0];vector<int>memo(n,-1);// Return minimum of cost to // climb (n-1)th stair and // cost to reach (n-2)th stairreturnmin(minCostRecur(n-1,cost,memo),minCostRecur(n-2,cost,memo));}intmain(){vector<int>cost={16,19,10,12,18};cout<<minCostClimbingStairs(cost)<<endl;return0;}
Java
// Java program to count number of// ways to reach nth stair.importjava.util.*;classGfG{staticintminCostRecur(inti,int[]cost,int[]memo){// Base caseif(i==0||i==1){returncost[i];}// If value is memoizedif(memo[i]!=-1)returnmemo[i];returnmemo[i]=cost[i]+Math.min(minCostRecur(i-1,cost,memo),minCostRecur(i-2,cost,memo));}staticintminCostClimbingStairs(int[]cost){intn=cost.length;if(n==1)returncost[0];int[]memo=newint[n];Arrays.fill(memo,-1);// Return minimum of cost to // climb (n-1)th stair and // cost to reach (n-2)th stairreturnMath.min(minCostRecur(n-1,cost,memo),minCostRecur(n-2,cost,memo));}publicstaticvoidmain(String[]args){int[]cost={16,19,10,12,18};System.out.println(minCostClimbingStairs(cost));}}
Python
# Python program to count number of # ways to reach nth stair.defminCostRecur(i,cost,memo):# Base caseifi==0ori==1:returncost[i]# If value is memoizedifmemo[i]!=-1:returnmemo[i]memo[i]=cost[i]+min(minCostRecur(i-1,cost,memo),minCostRecur(i-2,cost,memo))returnmemo[i]defminCostClimbingStairs(cost):n=len(cost)ifn==1:returncost[0]memo=[-1]*n# Return minimum of cost to # climb (n-1)th stair and # cost to reach (n-2)th stairreturnmin(minCostRecur(n-1,cost,memo),minCostRecur(n-2,cost,memo))if__name__=="__main__":cost=[16,19,10,12,18]print(minCostClimbingStairs(cost))
C#
// C# program to count number of// ways to reach nth stair.usingSystem;classGfG{staticintminCostRecur(inti,int[]cost,int[]memo){// Base caseif(i==0||i==1){returncost[i];}// If value is memoizedif(memo[i]!=-1)returnmemo[i];returnmemo[i]=cost[i]+Math.Min(minCostRecur(i-1,cost,memo),minCostRecur(i-2,cost,memo));}staticintminCostClimbingStairs(int[]cost){intn=cost.Length;if(n==1)returncost[0];int[]memo=newint[n];for(inti=0;i<n;i++)memo[i]=-1;// Return minimum of cost to // climb (n-1)th stair and // cost to reach (n-2)th stairreturnMath.Min(minCostRecur(n-1,cost,memo),minCostRecur(n-2,cost,memo));}staticvoidMain(string[]args){int[]cost={16,19,10,12,18};Console.WriteLine(minCostClimbingStairs(cost));}}
JavaScript
// JavaScript program to count number of// ways to reach nth stair.functionminCostRecur(i,cost,memo){// Base caseif(i===0||i===1){returncost[i];}// If value is memoizedif(memo[i]!==-1)returnmemo[i];memo[i]=cost[i]+Math.min(minCostRecur(i-1,cost,memo),minCostRecur(i-2,cost,memo));returnmemo[i];}functionminCostClimbingStairs(cost){letn=cost.length;if(n===1)returncost[0];letmemo=newArray(n).fill(-1);// Return minimum of cost to // climb (n-1)th stair and // cost to reach (n-2)th stairreturnMath.min(minCostRecur(n-1,cost,memo),minCostRecur(n-2,cost,memo));}letcost=[16,19,10,12,18];console.log(minCostClimbingStairs(cost));
Output
31
[Better Approach 2] Using Bottom-Up DP (Tabulation) - O(n) Time and O(n) Space
The idea is to create a1-D array, fill values for first two stairs and compute the values from 2 to n using the previous two results. For i = 2 to n, do dp[i] = cost[i] + min(dp[i-1] + dp[i-2]).
Illustration:
C++
// C++ program to count number of// ways to reach nth stair.#include<bits/stdc++.h>usingnamespacestd;intminCostClimbingStairs(vector<int>&cost){intn=cost.size();if(n==1)returncost[0];vector<int>dp(n);dp[0]=cost[0];dp[1]=cost[1];for(inti=2;i<n;i++){dp[i]=cost[i]+min(dp[i-1],dp[i-2]);}// Return minimum of cost to // climb (n-1)th stair and // cost to reach (n-2)th stairreturnmin(dp[n-1],dp[n-2]);}intmain(){vector<int>cost={16,19,10,12,18};cout<<minCostClimbingStairs(cost)<<endl;return0;}
Java
// Java program to count number of// ways to reach nth stair.importjava.util.*;classGfG{staticintminCostClimbingStairs(int[]cost){intn=cost.length;if(n==1)returncost[0];int[]dp=newint[n];dp[0]=cost[0];dp[1]=cost[1];for(inti=2;i<n;i++){dp[i]=cost[i]+Math.min(dp[i-1],dp[i-2]);}// Return minimum of cost to // climb (n-1)th stair and // cost to reach (n-2)th stairreturnMath.min(dp[n-1],dp[n-2]);}publicstaticvoidmain(String[]args){int[]cost={16,19,10,12,18};System.out.println(minCostClimbingStairs(cost));}}
Python
# Python program to count number of # ways to reach nth stair.defminCostClimbingStairs(cost):n=len(cost)ifn==1:returncost[0]dp=[0]*ndp[0]=cost[0]dp[1]=cost[1]foriinrange(2,n):dp[i]=cost[i]+min(dp[i-1],dp[i-2])# Return minimum of cost to # climb (n-1)th stair and # cost to reach (n-2)th stairreturnmin(dp[n-1],dp[n-2])if__name__=="__main__":cost=[16,19,10,12,18]print(minCostClimbingStairs(cost))
C#
// C# program to count number of// ways to reach nth stair.usingSystem;classGfG{staticintminCostClimbingStairs(int[]cost){intn=cost.Length;if(n==1)returncost[0];int[]dp=newint[n];dp[0]=cost[0];dp[1]=cost[1];for(inti=2;i<n;i++){dp[i]=cost[i]+Math.Min(dp[i-1],dp[i-2]);}// Return minimum of cost to // climb (n-1)th stair and // cost to reach (n-2)th stairreturnMath.Min(dp[n-1],dp[n-2]);}staticvoidMain(string[]args){int[]cost={16,19,10,12,18};Console.WriteLine(minCostClimbingStairs(cost));}}
JavaScript
// JavaScript program to count number of// ways to reach nth stair.functionminCostClimbingStairs(cost){letn=cost.length;if(n===1)returncost[0];letdp=newArray(n);dp[0]=cost[0];dp[1]=cost[1];for(leti=2;i<n;i++){dp[i]=cost[i]+Math.min(dp[i-1],dp[i-2]);}// Return minimum of cost to // climb (n-1)th stair and // cost to reach (n-2)th stairreturnMath.min(dp[n-1],dp[n-2]);}letcost=[16,19,10,12,18];console.log(minCostClimbingStairs(cost));
Output
31
[Expected Approach] Using Space Optimized DP – O(n) Time and O(1) Space
The idea is to store only the previous two computed values. We can observe that for a given stair, only the result of last two stairs are needed. So only store these two values and update them after each step.
C++
// C++ program to count number of// ways to reach nth stair.#include<bits/stdc++.h>usingnamespacestd;intminCostClimbingStairs(vector<int>&cost){intn=cost.size();if(n==1)returncost[0];intprev2=cost[0];intprev1=cost[1];for(inti=2;i<n;i++){intcurr=cost[i]+min(prev1,prev2);prev2=prev1;prev1=curr;}// Return minimum of cost to // climb (n-1)th stair and // cost to reach (n-2)th stairreturnmin(prev1,prev2);}intmain(){vector<int>cost={16,19,10,12,18};cout<<minCostClimbingStairs(cost)<<endl;return0;}
Java
// Java program to count number of// ways to reach nth stair.importjava.util.*;classGfG{staticintminCostClimbingStairs(int[]cost){intn=cost.length;if(n==1)returncost[0];intprev2=cost[0];intprev1=cost[1];for(inti=2;i<n;i++){intcurr=cost[i]+Math.min(prev1,prev2);prev2=prev1;prev1=curr;}// Return minimum of cost to // climb (n-1)th stair and // cost to reach (n-2)th stairreturnMath.min(prev1,prev2);}publicstaticvoidmain(String[]args){int[]cost={16,19,10,12,18};System.out.println(minCostClimbingStairs(cost));}}
Python
# Python program to count number of # ways to reach nth stair.defminCostClimbingStairs(cost):n=len(cost)ifn==1:returncost[0]prev2=cost[0]prev1=cost[1]foriinrange(2,n):curr=cost[i]+min(prev1,prev2)prev2=prev1prev1=curr# Return minimum of cost to # climb (n-1)th stair and # cost to reach (n-2)th stairreturnmin(prev1,prev2)if__name__=="__main__":cost=[16,19,10,12,18]print(minCostClimbingStairs(cost))
C#
// C# program to count number of// ways to reach nth stair.usingSystem;classGfG{staticintminCostClimbingStairs(int[]cost){intn=cost.Length;if(n==1)returncost[0];intprev2=cost[0];intprev1=cost[1];for(inti=2;i<n;i++){intcurr=cost[i]+Math.Min(prev1,prev2);prev2=prev1;prev1=curr;}// Return minimum of cost to // climb (n-1)th stair and // cost to reach (n-2)th stairreturnMath.Min(prev1,prev2);}staticvoidMain(string[]args){int[]cost={16,19,10,12,18};Console.WriteLine(minCostClimbingStairs(cost));}}
JavaScript
// JavaScript program to count number of// ways to reach nth stair.functionminCostClimbingStairs(cost){letn=cost.length;if(n===1)returncost[0];letprev2=cost[0];letprev1=cost[1];for(leti=2;i<n;i++){letcurr=cost[i]+Math.min(prev1,prev2);prev2=prev1;prev1=curr;}// Return minimum of cost to // climb (n-1)th stair and // cost to reach (n-2)th stairreturnMath.min(prev1,prev2);}letcost=[16,19,10,12,18];console.log(minCostClimbingStairs(cost));