Minimum Cost to Reach the Top (original) (raw)

Given an array of integers **cost[] of length **n, where **cost[i] is the cost of the i th 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.

Climbing-Stairs-1

**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].

Climbing-Stairs-2

Table of Content

[Naive Approach] Using Recursion - O(2^n) Time and O(n) Space

This problem is an extension of problem: Climbing Stairs to reach at the top.

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++ `

// C++ program to count number of // ways to reach nth stair. #include <bits/stdc++.h> using namespace std;

int minCostRecur(int i, vector &cost) {

// Base case
if (i==0 || i==1) {
    return cost[i];
}

return cost[i] + min(minCostRecur(i-1, cost), 
                     minCostRecur(i-2, cost));

}

int minCostClimbingStairs(vector &cost) { int n = cost.size();

if (n==1) return cost[0];

// Return minimum of cost to 
// reach (n-1)th stair and 
// cost to reach (n-2)th stair
return min(minCostRecur(n-1, cost), 
            minCostRecur(n-2, cost));

}

int main() { vector cost = { 16, 19, 10, 12, 18 }; cout << minCostClimbingStairs(cost) << endl; return 0; }

Java

// Java program to count number of // ways to reach nth stair. import java.util.*;

class GfG {

static int minCostRecur(int i, int[] cost) {
    
    // Base case
    if (i == 0 || i == 1) {
        return cost[i];
    }
    
    return cost[i] + Math.min(minCostRecur(i - 1, cost), 
                              minCostRecur(i - 2, cost));
}

static int minCostClimbingStairs(int[] cost) {
    int n = cost.length;
    
    if (n == 1) return cost[0];
    
    // Return minimum of cost to  
    // reach (n-1)th stair and  
    // cost to reach (n-2)th stair
    return Math.min(minCostRecur(n - 1, cost), 
                    minCostRecur(n - 2, cost));
}

public static void main(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.

def minCostRecur(i, cost):

# Base case
if i == 0 or i == 1:
    return cost[i]

return cost[i] + min(minCostRecur(i - 1, cost), 
                     minCostRecur(i - 2, cost))

def minCostClimbingStairs(cost): n = len(cost)

if n == 1:
    return cost[0]

# Return minimum of cost to 
# reach (n-1)th stair and 
# cost to reach (n-2)th stair
return min(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.

using System;

class GfG {

static int minCostRecur(int i, int[] cost) {
    
    // Base case
    if (i == 0 || i == 1) {
        return cost[i];
    }
    
    return cost[i] + Math.Min(minCostRecur(i - 1, cost), 
                              minCostRecur(i - 2, cost));
}

static int minCostClimbingStairs(int[] cost) {
    int n = cost.Length;
    
    if (n == 1) return cost[0];
    
    // Return minimum of cost to reach (n-1)th   
    // stair and cost to reach (n-2)th stair
    return Math.Min(minCostRecur(n - 1, cost), 
                    minCostRecur(n - 2, cost));
}

static void Main(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. function minCostRecur(i, cost) {

// Base case
if (i === 0 || i === 1) {
    return cost[i];
}

return cost[i] + Math.min(minCostRecur(i - 1, cost), 
                          minCostRecur(i - 2, cost));

}

function minCostClimbingStairs(cost) { let n = cost.length;

if (n === 1) return cost[0];

// Return minimum of cost to reach (n-1)th stair and  
// cost to reach (n-2)th stair
return Math.min(minCostRecur(n - 1, cost), 
                minCostRecur(n - 2, cost));

}

// Driver Code let cost = [16, 19, 10, 12, 18]; console.log(minCostClimbingStairs(cost));

`

[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.

// C++ program to count number of // ways to reach nth stair. #include <bits/stdc++.h> using namespace std;

int minCostRecur(int i, vector &cost, vector &memo) {

// Base case
if (i==0 || i==1) {
    return cost[i];
}

// If value is memoized
if (memo[i]!=-1) return memo[i];

return memo[i] = cost[i] + 
min(minCostRecur(i-1, cost, memo), 
minCostRecur(i-2, cost, memo));

}

int minCostClimbingStairs(vector &cost) { int n = cost.size();

if (n==1) return cost[0];

vector<int> memo(n, -1);

// Return minimum of cost to 
// climb (n-1)th stair and 
// cost to reach (n-2)th stair
return min(minCostRecur(n-1, cost, memo), 
           minCostRecur(n-2, cost, memo));

}

int main() { vector cost = { 16, 19, 10, 12, 18 }; cout << minCostClimbingStairs(cost) << endl; return 0; }

Java

// Java program to count number of // ways to reach nth stair. import java.util.*;

class GfG {

static int minCostRecur(int i, int[] cost, int[] memo) {
    
    // Base case
    if (i == 0 || i == 1) {
        return cost[i];
    }
    
    // If value is memoized
    if (memo[i] != -1) return memo[i];
    
    return memo[i] = cost[i] + 
    Math.min(minCostRecur(i - 1, cost, memo), 
    minCostRecur(i - 2, cost, memo));
}

static int minCostClimbingStairs(int[] cost) {
    int n = cost.length;
    
    if (n == 1) return cost[0];
    
    int[] memo = new int[n];
    Arrays.fill(memo, -1);
    
    // Return minimum of cost to  
    // climb (n-1)th stair and  
    // cost to reach (n-2)th stair
    return Math.min(minCostRecur(n - 1, cost, memo), 
                    minCostRecur(n - 2, cost, memo));
}

public static void main(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.

def minCostRecur(i, cost, memo):

# Base case
if i == 0 or i == 1:
    return cost[i]

# If value is memoized
if memo[i] != -1:
    return memo[i]

memo[i] = cost[i] + min(minCostRecur(i - 1, cost, memo), 
minCostRecur(i - 2, cost, memo))
return memo[i]

def minCostClimbingStairs(cost): n = len(cost)

if n == 1:
    return cost[0]

memo = [-1] * n

# Return minimum of cost to 
# climb (n-1)th stair and 
# cost to reach (n-2)th stair
return min(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. using System;

class GfG {

static int minCostRecur(int i, int[] cost, int[] memo) {
    
    // Base case
    if (i == 0 || i == 1) {
        return cost[i];
    }
    
    // If value is memoized
    if (memo[i] != -1) return memo[i];
    
    return memo[i] = cost[i] + 
                     Math.Min(minCostRecur(i - 1, cost, memo), 
                              minCostRecur(i - 2, cost, memo));
}

static int minCostClimbingStairs(int[] cost) {
    int n = cost.Length;
    
    if (n == 1) return cost[0];
    
    int[] memo = new int[n];
    for (int i = 0; i < n; i++) memo[i] = -1;
    
    // Return minimum of cost to  
    // climb (n-1)th stair and  
    // cost to reach (n-2)th stair
    return Math.Min(minCostRecur(n - 1, cost, memo), 
                    minCostRecur(n - 2, cost, memo));
}

static void Main(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.

function minCostRecur(i, cost, memo) {

// Base case
if (i === 0 || i === 1) {
    return cost[i];
}

// If value is memoized
if (memo[i] !== -1) return memo[i];

memo[i] = cost[i] + Math.min(minCostRecur(i - 1, cost, memo), 
                             minCostRecur(i - 2, cost, memo));
return memo[i];

}

function minCostClimbingStairs(cost) { let n = cost.length;

if (n === 1) return cost[0];

let memo = new Array(n).fill(-1);

// Return minimum of cost to  
// climb (n-1)th stair and  
// cost to reach (n-2)th stair
return Math.min(minCostRecur(n - 1, cost, memo), 
                minCostRecur(n - 2, cost, memo));

}

let cost = [16, 19, 10, 12, 18]; console.log(minCostClimbingStairs(cost));

`

[Better Approach 2] Using Bottom-Up DP (Tabulation) - O(n) Time and O(n) Space

_The idea is to create a**1-D **array, _fill values for first **t**wo 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> using namespace std;

int minCostClimbingStairs(vector &cost) { int n = cost.size();

if (n==1) return cost[0];

vector<int> dp(n);
dp[0] = cost[0];
dp[1] = cost[1];

for (int i=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 stair
return min(dp[n-1], dp[n-2]);

}

int main() { vector cost = { 16, 19, 10, 12, 18 }; cout << minCostClimbingStairs(cost) << endl; return 0; }

Java

// Java program to count number of // ways to reach nth stair. import java.util.*;

class GfG {

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

public static void main(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.

def minCostClimbingStairs(cost): n = len(cost)

if n == 1:
    return cost[0]

dp = [0] * n
dp[0] = cost[0]
dp[1] = cost[1]

for i in range(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 stair
return min(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.

using System;

class GfG {

static int minCostClimbingStairs(int[] cost) {
    int n = cost.Length;
    
    if (n == 1) return cost[0];
    
    int[] dp = new int[n];
    dp[0] = cost[0];
    dp[1] = cost[1];
    
    for (int i = 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 stair
    return Math.Min(dp[n - 1], dp[n - 2]);
}

static void Main(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.

function minCostClimbingStairs(cost) { let n = cost.length;

if (n === 1) return cost[0];

let dp = new Array(n);
dp[0] = cost[0];
dp[1] = cost[1];

for (let i = 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 stair
return Math.min(dp[n - 1], dp[n - 2]);

}

let cost = [16, 19, 10, 12, 18]; console.log(minCostClimbingStairs(cost));

`

[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> using namespace std;

int minCostClimbingStairs(vector &cost) { int n = cost.size();

if (n==1) return cost[0];

int prev2 = cost[0];
int prev1 = cost[1];

for (int i=2; i<n; i++) {
    int curr = 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 stair
return min(prev1, prev2);

}

int main() { vector cost = { 16, 19, 10, 12, 18 }; cout << minCostClimbingStairs(cost) << endl; return 0; }

Java

// Java program to count number of // ways to reach nth stair.

import java.util.*;

class GfG {

static int minCostClimbingStairs(int[] cost) {
    int n = cost.length;
    
    if (n == 1) return cost[0];

    int prev2 = cost[0];
    int prev1 = cost[1];
    
    for (int i = 2; i < n; i++) {
        int curr = 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 stair
    return Math.min(prev1, prev2);
}

public static void main(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.

def minCostClimbingStairs(cost): n = len(cost)

if n == 1:
    return cost[0]

prev2 = cost[0]
prev1 = cost[1]

for i in range(2, n):
    curr = 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 stair
return min(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.

using System;

class GfG {

static int minCostClimbingStairs(int[] cost) {
    int n = cost.Length;
    
    if (n == 1) return cost[0];

    int prev2 = cost[0];
    int prev1 = cost[1];
    
    for (int i = 2; i < n; i++) {
        int curr = 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 stair
    return Math.Min(prev1, prev2);
}

static void Main(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. function minCostClimbingStairs(cost) { let n = cost.length;

if (n === 1) return cost[0];

let prev2 = cost[0];
let prev1 = cost[1];

for (let i = 2; i < n; i++) {
    let curr = 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 stair
return Math.min(prev1, prev2);

}

let cost = [16, 19, 10, 12, 18]; console.log(minCostClimbingStairs(cost));

`