Open In App

Pyramid form (increasing then decreasing) consecutive array using reduce operations

Improve
Improve
Like Article
Like
Save
Share
Report

We have N (where N > 2) stones of various heights laid out in a row. The task is to make a pyramid from a given array of stones. In a pyramid, the height of the stones starts from 1, increase by 1, until it reaches some value x, then decreases by 1 until it reaches 1 again i.e. the stones should be 1, 2, 3, 4…x – 1, x, x – 1, x – 2 … 1. All other stones not part of the pyramid should have a height 0. We cannot move any of the stones from their current position, however, by paying a fee of 1, we can reduce the heights of the stones. We wish to minimize the cost of building a pyramid. Output the minimum cost to build this pyramid.

Examples: 

Input  : 1 2 3 4 2 1
Output : 4
The best pyramid that can be formed in this case is: 
1 2 3 2 1 0
The cost is thus:
(4 - 2) + (2 - 1) + (1 - 0) = 4

Input  : 1 5 2
Output : 4
We make a pyramid 1 2 1

Input  : 1 2 1
Output : 0
We already have a pyramid, we do not need to do any 
further construction.
Recommended Practice

By using simple logic, we can prove that the pyramid with the least cost of construction would be that of the maximum height. Also, two temples of same heights would cost the same to construct. 
This can be shown as follows: 
Assume the cost of demolishing all the stones to height 0 is x. 
Assume the cost of demolishing a temple of height h to height 0 is y. 
Then, if it is possible to construct a temple of height h from given stones, its cost would be x – y.
By using this, we can simplify our approach to two main steps: 
1. Identify the pyramid of maximum height that can be formed. 
2. Calculate the cost of constructing such a pyramid.
Step 2 can be completed in O(N) time complexity assuming we know where our pyramid is placed. 
Thus, our focus should be on decreasing the time complexity of step 1.

Naive Approach:
For each position in the array, we can assume the pyramid starts at that point. We then find the cost of constructing a temple of maximum height from 1 onwards, until a higher height is not possible, that is, assume a pyramid of height 1 is the maximum, then assume 2 is maximum and so on. Out of each of these costs, we then choose the minimum. 
This approach uses a time complexity of O(N^3).

Improved Approach:
For each position, assume it is the center of a temple. Move to the left and right of this point and attempt to find the maximum height of the temple. 
This can be done by setting the maximum of height of a temple at position i to be H(i) where H(i) is the height of the stone at that point. We then move to the left. If the height of the stone at this point is less than H(i) – 1, we set the maximum height to now be H(i – 1) + 1. In this way we identify the maximum height for each position. 
This approach uses a time complexity of O(N^2).

Dynamic Programming Approach:
By modifying the above algorithm slightly, we can attempt to get an O(N) approach. Start at the left, and moving right, find the maximum possible height pyramid that can be created at that position. Assume that the part of the array to the right of that position is a mirror image of the left. If H(i) is the height of stone at position i, then maxHeight(i) = Minimum(H(i), i, maxHeight(i – 1)) 
This can be explained as follows: 
The maximum possible height cannot exceed H(i) as we can only decrease the height of stone, not increase. 
The maximum possible height cannot exceed i, as the pyramid has to start from a height 1. 
The maximum possible height cannot exceed the maximum possible height of the stone before it – 1, as the stones have to increase by 1 for each step.
We calculate a similar value moving from right to left. We then take the minimum of these values for each position. Then by identifying the maximum, we can calculate the minimum cost of constructing a pyramid. 

C++




// Program to find minimum cost for pyramid
// from given array
#include <iostream>
using namespace std;
 
#define ull unsigned long long
 
// Returns minimum cost to form a pyramid
ull minPyramidCost(ull arr[], ull N)
{
    // Store the maximum possible pyramid height
    ull *left = new ull[N];
    ull *right = new ull[N];
 
    // Maximum height at start is 1
    left[0] = min(arr[0], (ull)1);
 
    // For each position calculate maximum height
    for (int i = 1; i < N; ++i)
        left[i] = min(arr[i],
                      min(left[i - 1] + 1, (ull)i + 1));
 
    // Maximum height at end is 1
    right[N - 1] = min(arr[N - 1], (ull)1);
 
    // For each position calculate maximum height
    for (int i = N - 2; i >= 0; --i)
        right[i] = min(arr[i],
                       min(right[i + 1] + 1, N - i));
 
    // Find minimum possible among calculated values
    ull tot[N];
    for (int i = 0; i < N; ++i)
        tot[i] = min(right[i], left[i]);
 
    // Find maximum height of pyramid
    ull max_ind = 0;
    for (int i = 0; i < N; ++i)
        if (tot[i] > tot[max_ind])
            max_ind = i;
 
    // Calculate cost of this pyramid
    ull cost = 0;
    ull height = tot[max_ind];
 
    // Calculate cost of left half
    for (int x = max_ind; x >= 0; --x)
    {
        cost += arr[x] - height;
        if (height > 0)
            --height;
    }
 
    // Calculate cost of right half
    height = tot[max_ind] - 1;
    for (int x = max_ind + 1; x < N; ++x)
    {
        cost += arr[x] - height;
        if (height > 0)
            --height;
    }
    return cost;
}
 
// Driver code
int main()
{
    ull arr[] = {1, 2, 3, 4, 2, 1};
    ull N = sizeof(arr)/sizeof(arr[0]);
    cout << minPyramidCost(arr, N);
    return 0;
}


Java




// Java program to find minimum cost for
// pyramid from given array
import java.util.*;
 
class GFG{
 
// Returns minimum cost to form a pyramid
static int minPyramidCost(int arr[], int N)
{
     
    // Store the maximum possible pyramid height
    int left[] = new int[N];
    int right[] = new int[N];
 
    // Maximum height at start is 1
    left[0] = Math.min(arr[0], 1);
 
    // For each position calculate maximum height
    for(int i = 1; i < N; ++i)
        left[i] = Math.min(arr[i],
                           Math.min(left[i - 1] + 1,
                                         i + 1));
                                          
    // Maximum height at end is 1
    right[N - 1] = Math.min(arr[N - 1], 1);
 
    // For each position calculate maximum height
    for(int i = N - 2; i >= 0; --i)
        right[i] = Math.min(arr[i],
                            Math.min(right[i + 1] + 1,
                                           N - i));
                                            
    // Find minimum possible among
    // calculated values
    int tot[] = new int[N];
    for(int i = 0; i < N; ++i)
        tot[i] = Math.min(right[i], left[i]);
 
    // Find maximum height of pyramid
    int max_ind = 0;
    for(int i = 0; i < N; ++i)
        if (tot[i] > tot[max_ind])
            max_ind = i;
 
    // Calculate cost of this pyramid
    int cost = 0;
    int height = tot[max_ind];
 
    // Calculate cost of left half
    for(int x = max_ind; x >= 0; --x)
    {
        cost += arr[x] - height;
        if (height > 0)
            --height;
    }
 
    // Calculate cost of right half
    height = tot[max_ind] - 1;
    for(int x = max_ind + 1; x < N; ++x)
    {
        cost += arr[x] - height;
        if (height > 0)
            --height;
    }
    return cost;
}
 
// Driver code
public static void main(String[] args)
{
    int arr[] = { 1, 2, 3, 4, 2, 1 };
    int N = arr.length;
     
    System.out.print(minPyramidCost(arr, N));
}
}
 
// This code is contributed by chitranayal   


Python3




# Program to find minimum cost for pyramid
# from given array
 
# Returns minimum cost to form a pyramid
def minPyramidCost(arr: list, N):
 
    # Store the maximum possible pyramid height
    left = [0] * N
    right = [0] * N
 
    # Maximum height at start is 1
    left[0] = min(arr[0], 1)
 
    # For each position calculate maximum height
    for i in range(1, N):
        left[i] = min(arr[i],
                  min(left[i - 1] + 1, i + 1))
 
    # Maximum height at end is 1
    right[N - 1] = min(arr[N - 1], 1)
 
    # For each position calculate maximum height
    for i in range(N - 2, -1, -1):
        right[i] = min(arr[i],
                   min(right[i + 1] + 1, N - i))
 
    # Find minimum possible among calculated values
    tot = [0] * N
    for i in range(N):
        tot[i] = min(right[i], left[i])
 
    # Find maximum height of pyramid
    max_ind = 0
    for i in range(N):
        if tot[i] > tot[max_ind]:
            max_ind = i
 
    # Calculate cost of this pyramid
    cost = 0
    height = tot[max_ind]
 
    # Calculate cost of left half
    for x in range(max_ind, -1, -1):
        cost += arr[x] - height
        if height > 0:
            height -= 1
 
    # Calculate cost of right half
    height = tot[max_ind] - 1
    for x in range(max_ind + 1, N):
        cost += arr[x] - height
        if height > 0:
            height -= 1
 
    return cost
 
# Driver Code
if __name__ == "__main__":
    arr = [1, 2, 3, 4, 2, 1]
    N = len(arr)
    print(minPyramidCost(arr, N))
 
# This code is contributed by
# sanjeev2552


C#




// C# program to find minimum cost for
// pyramid from given array
using System;
 
public class GFG
{
     
    // Returns minimum cost to form a pyramid
static int minPyramidCost(int[] arr, int N)
{
       
    // Store the maximum possible pyramid height
    int[] left = new int[N];
    int[] right = new int[N];
   
    // Maximum height at start is 1
    left[0] = Math.Min(arr[0], 1);
   
    // For each position calculate maximum height
    for(int i = 1; i < N; ++i)
        left[i] = Math.Min(arr[i],
                           Math.Min(left[i - 1] + 1,
                                         i + 1));
                                            
    // Maximum height at end is 1
    right[N - 1] = Math.Min(arr[N - 1], 1);
   
    // For each position calculate maximum height
    for(int i = N - 2; i >= 0; --i)
        right[i] = Math.Min(arr[i],
                            Math.Min(right[i + 1] + 1,
                                           N - i));
                                              
    // Find minimum possible among
    // calculated values
    int[] tot = new int[N];
    for(int i = 0; i < N; ++i)
        tot[i] = Math.Min(right[i], left[i]);
   
    // Find maximum height of pyramid
    int max_ind = 0;
    for(int i = 0; i < N; ++i)
        if (tot[i] > tot[max_ind])
            max_ind = i;
   
    // Calculate cost of this pyramid
    int cost = 0;
    int height = tot[max_ind];
   
    // Calculate cost of left half
    for(int x = max_ind; x >= 0; --x)
    {
        cost += arr[x] - height;
        if (height > 0)
            --height;
    }
   
    // Calculate cost of right half
    height = tot[max_ind] - 1;
    for(int x = max_ind + 1; x < N; ++x)
    {
        cost += arr[x] - height;
        if (height > 0)
            --height;
    }
    return cost;
}
   
// Driver code
    static public void Main ()
    {
        int[] arr = { 1, 2, 3, 4, 2, 1 };
        int N = arr.Length;
       
        Console.WriteLine(minPyramidCost(arr, N));
    }
}
 
// This code is contributed by avanitrachhadiya2155


Javascript




<script>
// Javascript program to find minimum cost for
// pyramid from given array
     
// Returns minimum cost to form a pyramid
function minPyramidCost(arr,N)
{
     
       // Store the maximum possible pyramid height
    let left = new Array(N);
    let right = new Array(N);
  
    // Maximum height at start is 1
    left[0] = Math.min(arr[0], 1);
  
    // For each position calculate maximum height
    for(let i = 1; i < N; ++i)
        left[i] = Math.min(arr[i],
                           Math.min(left[i - 1] + 1,
                                         i + 1));
                                           
    // Maximum height at end is 1
    right[N - 1] = Math.min(arr[N - 1], 1);
  
    // For each position calculate maximum height
    for(let i = N - 2; i >= 0; --i)
        right[i] = Math.min(arr[i],
                            Math.min(right[i + 1] + 1,
                                           N - i));
                                             
    // Find minimum possible among
    // calculated values
    let tot = new Array(N);
    for(let i = 0; i < N; ++i)
        tot[i] = Math.min(right[i], left[i]);
  
    // Find maximum height of pyramid
    let max_ind = 0;
    for(let i = 0; i < N; ++i)
        if (tot[i] > tot[max_ind])
            max_ind = i;
  
    // Calculate cost of this pyramid
    let cost = 0;
    let height = tot[max_ind];
  
    // Calculate cost of left half
    for(let x = max_ind; x >= 0; --x)
    {
        cost += arr[x] - height;
        if (height > 0)
            --height;
    }
  
    // Calculate cost of right half
    height = tot[max_ind] - 1;
    for(let x = max_ind + 1; x < N; ++x)
    {
        cost += arr[x] - height;
        if (height > 0)
            --height;
    }
    return cost;
    }
     
    // Driver code
    let arr=[1, 2, 3, 4, 2, 1 ];
    let  N = arr.length;
    document.write(minPyramidCost(arr, N));
     
    // This code is contributed by rag2127.
     
</script>


Output

4

Time Complexity: O(N)
Auxiliary Space: O(N)



Last Updated : 20 Dec, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads