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

28 Apr, 2021
We have N (where N > 2) stones of various heights laid out in a row. Task is to make a pyramid from given array of stones. In a pyramid, height of the stones start 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.
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++
Java
Python3
C#
Javascript
// 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 pyramidull 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 codeint main(){    ull arr[] = {1, 2, 3, 4, 2, 1};    ull N = sizeof(arr)/sizeof(arr[0]);    cout << minPyramidCost(arr, N);    return 0;}
// Java program to find minimum cost for// pyramid from given arrayimport java.util.*; class GFG{ // Returns minimum cost to form a pyramidstatic 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 codepublic 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   
# Program to find minimum cost for pyramid# from given array # Returns minimum cost to form a pyramiddef 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 Codeif __name__ == "__main__":    arr = [1, 2, 3, 4, 2, 1]    N = len(arr)    print(minPyramidCost(arr, N)) # This code is contributed by# sanjeev2552
// C# program to find minimum cost for// pyramid from given arrayusing System; public class GFG{         // Returns minimum cost to form a pyramidstatic 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
<script>// Javascript program to find minimum cost for// pyramid from given array     // Returns minimum cost to form a pyramidfunction 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
This approach runs in O(N) time complexity.This article is contributed by Aditya Kamath. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above. 
sanjeev2552
ukasp
avanitrachhadiya2155
rag2127
Dynamic Programming
Dynamic Programming
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Maximum size square sub-matrix with all 1s
Optimal Substructure Property in Dynamic Programming | DP-2
Optimal Binary Search Tree | DP-24
Min Cost Path | DP-6
Maximum Subarray Sum using Divide and Conquer algorithm
Greedy approach vs Dynamic programming
Maximum sum such that no two elements are adjacent
Word Break Problem | DP-32
3 Different ways to print Fibonacci series in Java
Top 50 Dynamic Programming Coding Problems for Interviews