Given an array arr[] of size n, where arr[i] denotes the height of stone i. Geek starts from stone 0 and from stone i, he can jump to stones i + 1, i + 2, ... i + k. The cost for jumping from stone i to stone j is abs(arr[i] - arr[j]). Find the minimum cost for Geek to reach the last stone.
Examples:
Input: n = 5, k = 3, arr[] = {10, 30, 40, 50, 20}
Output: 30
Explanation: Geek will follow the path 0->1->4, and the total cost would be | 10 - 30 | + | 30 - 20 | = 30.Input: n = 3, k = 1, arr[] = {10, 20, 10}
Output: 20
Explanation: Geek will follow the path 0->1->2, and the total cost would be | 10 - 20 | + | 20 - 10 | = 20.
Table of Content
[Naive Approach] Using Recursion - O(k ^ n) Time and O(n) Space
The idea is that we can reach the last stone from one of its previous k stones. So, we can find the minimum cost to reach stone i by using the minimum costs to reach stone (i - 1), (i - 2) .... (i - k). Since the problem is reduced to similar subproblems, we can use recursion.
Recurrence Relation:
minCostRec(i) = min(abs(arr[i] - arr[i - j]) + minCostRec(i - j))
for 1 <= j <= min(i, k), where minCostRec(i) is the minimum cost to reach stone i from stone 0.Base Case: minCostRec(0), return 0.
// C++ Program to find the minimum cost to reach last stone
// using recursion
#include <bits/stdc++.h>
using namespace std;
// Recursive function to find minimum cost to reach stone i
int minCostRec(int i, vector<int>& arr, int k) {
// Base Case
if (i == 0) return 0;
int cost = INT_MAX;
// Find the minimum cost to reach stone i by recursively
// finding the minimum cost to reach last k stones
for (int j = 1; j <= min(i, k); j++) {
cost = min(cost, abs(arr[i] - arr[i - j]) +
minCostRec(i - j, arr, k));
}
return cost;
}
// Wrapper function to find minimum cost to reach last stone
int minimizeCost(int k, vector<int>& arr) {
int n = arr.size();
return minCostRec(n - 1, arr, k);
}
int main() {
vector<int> arr = { 10, 30, 40, 50, 20 };
int k = 3;
cout << minimizeCost(k, arr);
return 0;
}
// C Program to find the minimum cost to reach last stone
// using recursion
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int min(int a, int b) {
return (a < b) ? a : b;
}
// Recursive function to find minimum cost to reach stone i
int minCostRec(int i, int* arr, int k) {
// Base Case
if (i == 0) return 0;
int cost = INT_MAX;
// Find the minimum cost to reach stone i by recursively
// finding the minimum cost to reach last k stones
for (int j = 1; j <= min(i, k); j++) {
cost = min(cost, abs(arr[i] - arr[i - j]) +
minCostRec(i - j, arr, k));
}
return cost;
}
// Wrapper function to find minimum cost to reach last stone
int minimizeCost(int k, int* arr, int n) {
return minCostRec(n - 1, arr, k);
}
int main() {
int arr[] = { 10, 30, 40, 50, 20 };
int k = 3;
int n = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", minimizeCost(k, arr, n));
return 0;
}
// Java Program to find the minimum cost to reach last stone
// using recursion
import java.util.Arrays;
class GfG {
// Recursive function to find minimum cost to reach stone i
static int minCostRec(int i, int[] arr, int k) {
// Base Case
if (i == 0) return 0;
int cost = Integer.MAX_VALUE;
// Find the minimum cost to reach stone i by recursively
// finding the minimum cost to reach last k stones
for (int j = 1; j <= Math.min(i, k); j++) {
cost = Math.min(cost, Math.abs(arr[i] - arr[i - j]) +
minCostRec(i - j, arr, k));
}
return cost;
}
// Wrapper function to find minimum cost to reach last stone
static int minimizeCost(int k, int[] arr) {
int n = arr.length;
return minCostRec(n - 1, arr, k);
}
public static void main(String[] args) {
int[] arr = { 10, 30, 40, 50, 20 };
int k = 3;
System.out.println(minimizeCost(k, arr));
}
}
# Python Program to find the minimum cost to reach last stone
# using recursion
# Recursive function to find minimum cost to reach stone i
def minCostRec(i, arr, k):
# Base Case
if i == 0:
return 0
cost = float('inf')
# Find the minimum cost to reach stone i by recursively
# finding the minimum cost to reach last k stones
for j in range(1, min(i, k) + 1):
cost = min(cost, abs(arr[i] - arr[i - j]) +
minCostRec(i - j, arr, k))
return cost
# Wrapper function to find minimum cost to reach last stone
def minimizeCost(k, arr):
n = len(arr)
return minCostRec(n - 1, arr, k)
if __name__ == "__main__":
arr = [10, 30, 40, 50, 20]
k = 3
print(minimizeCost(k, arr))
// C# Program to find the minimum cost to reach last stone
// using recursion
using System;
class GfG {
// Recursive function to find minimum cost to reach stone i
static int minCostRec(int i, int[] arr, int k) {
// Base Case
if (i == 0) return 0;
int cost = int.MaxValue;
// Find the minimum cost to reach stone i by recursively
// finding the minimum cost to reach last k stones
for (int j = 1; j <= Math.Min(i, k); j++) {
cost = Math.Min(cost, Math.Abs(arr[i] - arr[i - j]) +
minCostRec(i - j, arr, k));
}
return cost;
}
// Wrapper function to find minimum cost to reach last stone
static int minimizeCost(int k, int[] arr) {
int n = arr.Length;
return minCostRec(n - 1, arr, k);
}
static void Main(string[] args) {
int[] arr = { 10, 30, 40, 50, 20 };
int k = 3;
Console.WriteLine(minimizeCost(k, arr));
}
}
// JavaScript Program to find the minimum cost to reach last stone
// using recursion
// Recursive function to find minimum cost to reach stone i
function minCostRec(i, arr, k) {
// Base Case
if (i === 0) return 0;
let cost = Infinity;
// Find the minimum cost to reach stone i by recursively
// finding the minimum cost to reach last k stones
for (let j = 1; j <= Math.min(i, k); j++) {
cost = Math.min(cost, Math.abs(arr[i] - arr[i - j]) +
minCostRec(i - j, arr, k));
}
return cost;
}
// Wrapper function to find minimum cost to reach last stone
function minimizeCost(k, arr) {
const n = arr.length;
return minCostRec(n - 1, arr, k);
}
const arr = [10, 30, 40, 50, 20];
const k = 3;
console.log(minimizeCost(k, arr));
Output
30
Time Complexity: O(k ^ n) we are making k recursive calls for each stone.
Auxiliary Space: O(n), corresponding to the recursion depth.
[Better Approach] Using Memoization - O(n * k) Time and O(n) Space
We can see that the same subproblems are computed multiple times, minCostRec(i - 2) is computed in minCostRec(i) as well as minCostRec(i - 1).
Since we have optimal substructure and overlapping subproblems, we memoize the result of already computed subproblems by storing it in an array, memo[] such that memo[i] will store the minimum cost to reach stone i.
// C++ Program to find the minimum cost to reach last stone
// using memoization
#include <bits/stdc++.h>
using namespace std;
// Recursive function to find minimum cost to reach stone i
int minCostRec(int i, vector<int>& arr, int k, vector<int> &memo) {
// Base Case
if (i == 0) return 0;
// If the result for ith stone is already computed, return it
if(memo[i] != -1)
return memo[i];
int cost = INT_MAX;
// Find the minimum cost to reach stone i by recursively
// finding the minimum cost to reach last k stones
for (int j = 1; j <= min(i, k); j++) {
cost = min(cost, abs(arr[i] - arr[i - j]) +
minCostRec(i - j, arr, k, memo));
}
return memo[i] = cost;
}
// Wrapper function to find minimum cost to reach last stone
int minimizeCost(int k, vector<int>& arr) {
int n = arr.size();
vector<int> memo(n, -1);
return minCostRec(n - 1, arr, k, memo);
}
int main() {
vector<int> arr = { 10, 30, 40, 50, 20 };
int k = 3;
cout << minimizeCost(k, arr);
return 0;
}
// C Program to find the minimum cost to reach last stone
// using memoization
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
// Custom min function to return the minimum of two integers
int min(int a, int b) {
return (a < b) ? a : b;
}
// Recursive function to find minimum cost to reach stone i
int minCostRec(int i, int* arr, int k, int* memo) {
// Base Case
if (i == 0) return 0;
// If the result for ith stone is already computed, return it
if (memo[i] != -1)
return memo[i];
int cost = INT_MAX;
// Find the minimum cost to reach stone i by recursively
// finding the minimum cost to reach last k stones
for (int j = 1; j <= (i < k ? i : k); j++) {
cost = min(cost, abs(arr[i] - arr[i - j])
+ minCostRec(i - j, arr, k, memo));
}
return memo[i] = cost;
}
// Wrapper function to find minimum cost to reach last stone
int minimizeCost(int k, int* arr, int n) {
int memo[n];
for (int i = 0; i < n; i++) {
memo[i] = -1;
}
return minCostRec(n - 1, arr, k, memo);
}
int main() {
int arr[] = { 10, 30, 40, 50, 20 };
int k = 3;
int n = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", minimizeCost(k, arr, n));
return 0;
}
// Java Program to find the minimum cost to reach last stone
// using memoization
import java.util.Arrays;
class GfG {
// Recursive function to find minimum cost to reach stone i
static int minCostRec(int i, int[] arr, int k, int[] memo) {
// Base Case
if (i == 0) return 0;
// If the result for ith stone is already computed, return it
if (memo[i] != -1)
return memo[i];
int cost = Integer.MAX_VALUE;
// Find the minimum cost to reach stone i by recursively
// finding the minimum cost to reach last k stones
for (int j = 1; j <= Math.min(i, k); j++) {
cost = Math.min(cost, Math.abs(arr[i] - arr[i - j]) +
minCostRec(i - j, arr, k, memo));
}
return memo[i] = cost;
}
// Wrapper function to find minimum cost to reach last stone
static int minimizeCost(int k, int[] arr) {
int n = arr.length;
int[] memo = new int[n];
Arrays.fill(memo, -1);
return minCostRec(n - 1, arr, k, memo);
}
public static void main(String[] args) {
int[] arr = { 10, 30, 40, 50, 20 };
int k = 3;
System.out.println(minimizeCost(k, arr));
}
}
# Python Program to find the minimum cost to reach last stone
# using memoization
# Recursive function to find minimum cost to reach stone i
def minCostRec(i, arr, k, memo):
# Base Case
if i == 0:
return 0
# If the result for ith stone is already computed, return it
if memo[i] != -1:
return memo[i]
cost = float('inf')
# Find the minimum cost to reach stone i by recursively
# finding the minimum cost to reach last k stones
for j in range(1, min(i, k) + 1):
cost = min(cost, abs(arr[i] - arr[i - j]) +
minCostRec(i - j, arr, k, memo))
memo[i] = cost
return cost
# Wrapper function to find minimum cost to reach last stone
def minimizeCost(k, arr):
n = len(arr)
memo = [-1] * n
return minCostRec(n - 1, arr, k, memo)
if __name__ == "__main__":
arr = [10, 30, 40, 50, 20]
k = 3
print(minimizeCost(k, arr))
// C# Program to find the minimum cost to reach last stone
// using memoization
using System;
class GfG {
// Recursive function to find minimum cost to reach stone i
static int minCostRec(int i, int[] arr, int k, int[] memo) {
// Base Case
if (i == 0) return 0;
// If the result for ith stone is already computed, return it
if (memo[i] != -1)
return memo[i];
int cost = int.MaxValue;
// Find the minimum cost to reach stone i by recursively
// finding the minimum cost to reach last k stones
for (int j = 1; j <= Math.Min(i, k); j++) {
cost = Math.Min(cost, Math.Abs(arr[i] - arr[i - j]) +
minCostRec(i - j, arr, k, memo));
}
return memo[i] = cost;
}
// Wrapper function to find minimum cost to reach last stone
static int minimizeCost(int k, int[] arr) {
int n = arr.Length;
int[] memo = new int[n];
Array.Fill(memo, -1);
return minCostRec(n - 1, arr, k, memo);
}
static void Main() {
int[] arr = { 10, 30, 40, 50, 20 };
int k = 3;
Console.WriteLine(minimizeCost(k, arr));
}
}
// JavaScript Program to find the minimum cost to reach last stone
// using memoization
// Recursive function to find minimum cost to reach stone i
function minCostRec(i, arr, k, memo) {
// Base Case
if (i === 0) return 0;
// If the result for ith stone is already computed, return it
if (memo[i] !== -1) return memo[i];
let cost = Number.MAX_VALUE;
// Find the minimum cost to reach stone i by recursively
// finding the minimum cost to reach last k stones
for (let j = 1; j <= Math.min(i, k); j++) {
cost = Math.min(cost, Math.abs(arr[i] - arr[i - j]) +
minCostRec(i - j, arr, k, memo));
}
return memo[i] = cost;
}
// Wrapper function to find minimum cost to reach last stone
function minimizeCost(k, arr) {
const n = arr.length;
const memo = new Array(n).fill(-1);
return minCostRec(n - 1, arr, k, memo);
}
const arr = [10, 30, 40, 50, 20];
const k = 3;
console.log(minimizeCost(k, arr));
Output
30
[Expected Approach] Using Tabulation - O(n * k) Time and O(n) Space
Instead of starting from the last stone, we can start from the first stone, that is in bottom-up manner. So, calculate the minimum cost starting from stone 0 to n - 1. Also, we will store the minimum cost for each stone in a dp[] array, such that dp[i] stores the minimum cost to reach stone i.
dp[i] = min(abs(arr[i] - arr[i - j]) + dp[i - j]) for 1 <= j <= min(i, k)
// C++ Program to find the minimum cost to reach last stone
// using tabulation
#include <bits/stdc++.h>
using namespace std;
// function to find minimum cost to reach last stone
int minimizeCost(int k, vector<int>& arr) {
int n = arr.size();
vector<int> dp(n, INT_MAX);
// Base Case
dp[0] = 0;
for(int i = 1; i < n; i++) {
for(int j = 1; j <= min(i, k); j++) {
dp[i] = min(dp[i],
abs(arr[i] - arr[i - j]) + dp[i - j]);
}
}
return dp[n - 1];
}
int main() {
vector<int> arr = { 10, 30, 40, 50, 20 };
int k = 3;
cout << minimizeCost(k, arr);
return 0;
}
// C Program to find the minimum cost to reach last stone
// using tabulation
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
// Function to find minimum of two integers
int min(int a, int b) {
return (a < b) ? a : b;
}
// Function to find minimum cost to reach last stone
int minimizeCost(int k, int* arr, int n) {
int dp[n];
// Base Case
dp[0] = 0;
for (int i = 1; i < n; i++) {
dp[i] = INT_MAX;
for (int j = 1; j <= min(i, k); j++) {
dp[i] = min(dp[i], abs(arr[i] - arr[i - j]) + dp[i - j]);
}
}
return dp[n - 1];
}
int main() {
int arr[] = { 10, 30, 40, 50, 20 };
int k = 3;
int n = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", minimizeCost(k, arr, n));
return 0;
}
// Java Program to find the minimum cost to reach last stone
// using tabulation
import java.util.*;
class GfG {
// Function to find minimum cost to reach last stone
static int minimizeCost(int k, int[] arr) {
int n = arr.length;
int[] dp = new int[n];
Arrays.fill(dp, Integer.MAX_VALUE);
// Base Case
dp[0] = 0;
for (int i = 1; i < n; i++) {
for (int j = 1; j <= Math.min(i, k); j++) {
dp[i] = Math.min(dp[i],
Math.abs(arr[i] - arr[i - j]) + dp[i - j]);
}
}
return dp[n - 1];
}
public static void main(String[] args) {
int[] arr = { 10, 30, 40, 50, 20 };
int k = 3;
System.out.println(minimizeCost(k, arr));
}
}
# Python Program to find the minimum cost to reach last stone
# using tabulation
# Function to find minimum cost to reach last stone
def minimizeCost(k, arr):
n = len(arr)
dp = [float('inf')] * n
# Base Case
dp[0] = 0
for i in range(1, n):
for j in range(1, min(i, k) + 1):
dp[i] = min(dp[i],
abs(arr[i] - arr[i - j]) + dp[i - j])
return dp[n - 1]
if __name__ == "__main__":
arr = [10, 30, 40, 50, 20]
k = 3
print(minimizeCost(k, arr))
// C# Program to find the minimum cost to reach last stone
// using tabulation
using System;
class GfG {
// Function to find minimum cost to reach last stone
static int MinimizeCost(int k, int[] arr) {
int n = arr.Length;
int[] dp = new int[n];
// Base Case
dp[0] = 0;
for (int i = 1; i < n; i++) {
dp[i] = int.MaxValue;
for (int j = 1; j <= Math.Min(i, k); j++) {
dp[i] = Math.Min(dp[i],
Math.Abs(arr[i] - arr[i - j]) + dp[i - j]);
}
}
return dp[n - 1];
}
static void Main(string[] args) {
int[] arr = { 10, 30, 40, 50, 20 };
int k = 3;
Console.WriteLine(MinimizeCost(k, arr));
}
}
// JavaScript Program to find the minimum cost to reach last stone
// using tabulation
// Function to find minimum cost to reach last stone
function minimizeCost(k, arr) {
const n = arr.length;
const dp = new Array(n).fill(Infinity);
// Base Case
dp[0] = 0;
for (let i = 1; i < n; i++) {
for (let j = 1; j <= Math.min(i, k); j++) {
dp[i] = Math.min(dp[i],
Math.abs(arr[i] - arr[i - j]) + dp[i - j]);
}
}
return dp[n - 1];
}
const arr = [10, 30, 40, 50, 20];
const k = 3;
console.log(minimizeCost(k, arr));
Output
30