Largest Rectangular Area in a Histogram-Expected Approach

Spread the love

The concept rests on the innocent attitude. We find previous smaller and next smaller for the entire array in linear time instead of linearly finding previous smaller and next smaller for every element.

  • Using a stack with index of preceding smaller element for every item, build an array perS[] in O(n) time.
  • Using a stack with index of next smaller element for every item, create another array nextS[] in O(n) time.
  • Please follow for every element hist[i]. With hist[i] as the lowest height, find the breadth of the biggest histogram. width = nextS[i] – prevS[i] – 1. < The region is now hist[i] times breadth.
  • Step 3’s maximum of all values should be returned.

C++

#include <bits/stdc++.h>
using namespace std;

// Function to find next smaller for every element
vector<int> nextSmaller(vector<int>& hist) {
    int n = hist.size();
  
    // Initialize with n for the cases when next smaller
    // does not exist
    vector<int> nextS(n, n);
  
    stack<int> st;
 
    // Traverse all array elements from left to right
    for (int i = 0; i < n; ++i) {
        while (!st.empty() && hist[i] < hist[st.top()]) {

            // Setting the index of the next smaller element
            // for the top of the stack
            nextS[st.top()] = i;
            st.pop();
        }
        st.push(i);
    }
    return nextS;
}

// Function to find previous smaller for every element
vector<int> prevSmaller(vector<int>& hist) {
    int n = hist.size();
  
    // Initialize with -1 for the cases when prev smaller
    // does not exist
    vector<int> prevS(n, -1);
  
    stack<int> st;
 
    // Traverse all array elements from left to right
    for (int i = 0; i < n; ++i) {
        while (!st.empty() && hist[i] < hist[st.top()]) {

            // Setting the index of the previous smaller element
            //  for the top of the stack
            st.pop();
        }
        if (!st.empty()) {
            prevS[i] = st.top();
        }
        st.push(i);
    }
    return prevS;
}

// Helper function to calculate the maximum rectangular
// area in the histogram
int getMaxArea(vector<int>& hist) {
    vector<int> prevS = prevSmaller(hist);
    vector<int> nextS = nextSmaller(hist);
    
    int maxArea = 0;

    // Calculate the area for each histogram bar
    for (int i = 0; i < hist.size(); ++i) {
        int width = nextS[i] - prevS[i] - 1; 
        int area = hist[i] * width;          
        maxArea = max(maxArea, area);        
    }
    
    return maxArea;
}

int main() {
    vector<int> hist = {60, 20, 50, 40, 10, 50, 60};
    cout << getMaxArea(hist) << endl;
    return 0;
}

C

#include <stdio.h>
#include <stdlib.h>

// Stack structure
struct Stack {
    int top;
    int capacity;
    int* items;
};

// Function to create an empty stack with dynamic memory allocation
struct Stack* createStack(int capacity) {
    struct Stack* stack = 
                (struct Stack*)malloc(sizeof(struct Stack));
    stack->capacity = capacity;
    stack->top = -1;
    stack->items = (int*)malloc(stack->capacity * sizeof(int));
    return stack;
}

// Function to check if the stack is empty
int isEmpty(struct Stack* stack) {
    return stack->top == -1;
}

// Function to push an element onto the stack
void push(struct Stack* stack, int value) {
    if (stack->top == stack->capacity - 1) {
        printf("Stack overflow\n");
        return;
    }
    stack->items[++(stack->top)] = value;
}

// Function to pop an element from the stack
int pop(struct Stack* stack) {
    if (isEmpty(stack)) {
        printf("Stack underflow\n");
        return -1;
    }
    return stack->items[(stack->top)--];
}

// Function to get the top element of the stack
int peek(struct Stack* stack) {
    if (!isEmpty(stack)) {
        return stack->items[stack->top];
    }
    return -1;
}

// Function to find the next smaller element for every element
void nextSmaller(int hist[], int n, int nextS[]) {
    struct Stack* stack = createStack(n);

    // Initialize with n for the cases
    // when next smaller does not exist
    for (int i = 0; i < n; i++) {
        nextS[i] = n;
    }

    // Traverse all array elements from left to right
    for (int i = 0; i < n; i++) {
        while (!isEmpty(stack) && hist[i] < hist[peek(stack)]) {
            nextS[peek(stack)] = i;
            pop(stack);
        }
        push(stack, i);
    }
}

// Function to find the previous smaller element for every element
void prevSmaller(int hist[], int n, int prevS[]) {
    struct Stack* stack = createStack(n);

    // Initialize with -1 for the cases when prev smaller does not exist
    for (int i = 0; i < n; i++) {
        prevS[i] = -1;
    }

    // Traverse all array elements from left to right
    for (int i = 0; i < n; i++) {
        while (!isEmpty(stack) && hist[i] < hist[peek(stack)]) {
            pop(stack);
        }
        if (!isEmpty(stack)) {
            prevS[i] = peek(stack);
        }
        push(stack, i);
    }
}

// Helper function to calculate the maximum rectangular
// area in the histogram
int getMaxArea(int hist[], int n) {
    int* prevS = (int*)malloc(n * sizeof(int));
    int* nextS = (int*)malloc(n * sizeof(int));
    int maxArea = 0;

    // Find previous and next smaller elements
    prevSmaller(hist, n, prevS);
    nextSmaller(hist, n, nextS);

    // Calculate the area for each histogram bar
    for (int i = 0; i < n; i++) {
        int width = nextS[i] - prevS[i] - 1;
        int area = hist[i] * width;
        if (area > maxArea) {
            maxArea = area;
        }
    }
    return maxArea;
}

// Driver code
int main() {
    int hist[] = {60, 20, 50, 40, 10, 50, 60};
    int n = sizeof(hist) / sizeof(hist[0]);
    printf("Maximum Area: %d\n", getMaxArea(hist, n));
    return 0;
}

Java

import java.util.Stack;

class GfG {

    // Function to find next smaller for every element
    static int[] nextSmaller(int[] hist) {
        int n = hist.length;

        // Initialize with n for the cases when next smaller
        // does not exist
        int[] nextS = new int[n];
        for (int i = 0; i < n; i++) {
            nextS[i] = n;
        }

        Stack<Integer> st = new Stack<>();

        // Traverse all array elements from left to right
        for (int i = 0; i < n; i++) {
            while (!st.isEmpty() && hist[i] < hist[st.peek()]) {

                // Setting the index of the next smaller element
                // for the top of the stack
                nextS[st.pop()] = i;
            }
            st.push(i);
        }
        return nextS;
    }

    // Function to find previous smaller for every element
    static int[] prevSmaller(int[] hist) {
        int n = hist.length;

        // Initialize with -1 for the cases when prev smaller
        // does not exist
        int[] prevS = new int[n];
        for (int i = 0; i < n; i++) {
            prevS[i] = -1;
        }

        Stack<Integer> st = new Stack<>();

        // Traverse all array elements from left to right
        for (int i = 0; i < n; i++) {
            while (!st.isEmpty() && hist[i] < hist[st.peek()]) {
                st.pop();
            }
            if (!st.isEmpty()) {
                prevS[i] = st.peek();
            }
            st.push(i);
        }
        return prevS;
    }

    // Helper function to calculate the maximum rectangular
    // area in the histogram
    static int getMaxArea(int[] hist) {
        int[] prevS = prevSmaller(hist);
        int[] nextS = nextSmaller(hist);
        int maxArea = 0;

        // Calculate the area for each histogram bar
        for (int i = 0; i < hist.length; i++) {
            int width = nextS[i] - prevS[i] - 1;
            int area = hist[i] * width;
            maxArea = Math.max(maxArea, area);
        }
        return maxArea;
    }

    public static void main(String[] args) {
        int[] hist = {60, 20, 50, 40, 10, 50, 60};
        System.out.println(getMaxArea(hist));
    }
}

python

# Function to find next smaller for every element
def nextSmaller(hist):
    n = len(hist)
    
    # Initialize with n for the cases when next smaller
    # does not exist
    nextS = [n] * n
    st = []
    
    # Traverse all array elements from left to right
    for i in range(n):
        while st and hist[i] < hist[st[-1]]:
            # Setting the index of the next smaller element
            # for the top of the stack
            nextS[st.pop()] = i
        st.append(i)
    
    return nextS

# Function to find previous smaller for every element
def prevSmaller(hist):
    n = len(hist)
    
    # Initialize with -1 for the cases when prev smaller
    # does not exist
    prevS = [-1] * n
    st = []
    
    # Traverse all array elements from left to right
    for i in range(n):
        while st and hist[i] < hist[st[-1]]:
            st.pop()
        if st:
            prevS[i] = st[-1]
        st.append(i)
    
    return prevS

# Helper function to calculate the maximum rectangular
# area in the histogram
def getMaxArea(hist):
    prevS = prevSmaller(hist)
    nextS = nextSmaller(hist)
    maxArea = 0
    
    # Calculate the area for each histogram bar
    for i in range(len(hist)):
        width = nextS[i] - prevS[i] - 1
        area = hist[i] * width
        maxArea = max(maxArea, area)
    
    return maxArea

# Driver code
hist = [60, 20, 50, 40, 10, 50, 60]
print(getMaxArea(hist))

C#

using System;
using System.Collections.Generic;

class GfG {

    // Function to find next smaller for every element
    static int[] nextSmaller(int[] hist) {
        int n = hist.Length;

        // Initialize with n for the cases when next smaller
        // does not exist
        int[] nextS = new int[n];
        for (int i = 0; i < n; i++) {
            nextS[i] = n;
        }

        Stack<int> st = new Stack<int>();

        // Traverse all array elements from left to right
        for (int i = 0; i < n; i++) {
            while (st.Count > 0 && hist[i] < hist[st.Peek()]) {

                // Setting the index of the next smaller element
                // for the top of the stack
                nextS[st.Pop()] = i;
            }
            st.Push(i);
        }
        return nextS;
    }

    // Function to find previous smaller for every element
    static int[] prevSmaller(int[] hist) {
        int n = hist.Length;

        // Initialize with -1 for the cases when prev smaller
        // does not exist
        int[] prevS = new int[n];
        for (int i = 0; i < n; i++) {
            prevS[i] = -1;
        }

        Stack<int> st = new Stack<int>();

        // Traverse all array elements from left to right
        for (int i = 0; i < n; i++) {
            while (st.Count > 0 && hist[i] < hist[st.Peek()]) {
                st.Pop();
            }
            if (st.Count > 0) {
                prevS[i] = st.Peek();
            }
            st.Push(i);
        }
        return prevS;
    }

    // Helper function to calculate the maximum rectangular
    // area in the histogram
    static int getMaxArea(int[] hist) {
        int[] prevS = prevSmaller(hist);
        int[] nextS = nextSmaller(hist);
        int maxArea = 0;

        // Calculate the area for each histogram bar
        for (int i = 0; i < hist.Length; i++) {
            int width = nextS[i] - prevS[i] - 1;
            int area = hist[i] * width;
            maxArea = Math.Max(maxArea, area);
        }
        return maxArea;
    }

    static void Main() {
        int[] hist = {60, 20, 50, 40, 10, 50, 60};
        Console.WriteLine(getMaxArea(hist));
    }
}

JavaScript

// Function to find next smaller for every element
function nextSmaller(hist){
    const n = hist.length;

    // Initialize with n for the cases when next smaller
    // does not exist
    const nextS = new Array(n).fill(n);
    const stack = [];

    // Traverse all array elements from left to right
    for (let i = 0; i < n; i++) {
        while (stack.length
               && hist[i] < hist[stack[stack.length - 1]]) {
               
            // Setting the index of the next smaller element
            // for the top of the stack
            nextS[stack.pop()] = i;
        }
        stack.push(i);
    }

    return nextS;
}

// Function to find previous smaller for every element
function prevSmaller(hist)
{
    const n = hist.length;

    // Initialize with -1 for the cases when prev smaller
    // does not exist
    const prevS = new Array(n).fill(-1);
    const stack = [];

    // Traverse all array elements from left to right
    for (let i = 0; i < n; i++) {
        while (stack.length
               && hist[i] < hist[stack[stack.length - 1]]) {
            stack.pop();
        }
        if (stack.length) {
            prevS[i] = stack[stack.length - 1];
        }
        stack.push(i);
    }

    return prevS;
}

// Helper function to calculate the maximum rectangular
// area in the histogram
function getMaxArea(hist)
{
    const prevS = prevSmaller(hist);
    const nextS = nextSmaller(hist);
    let maxArea = 0;

    // Calculate the area for each histogram bar
    for (let i = 0; i < hist.length; i++) {
        const width = nextS[i] - prevS[i] - 1;
        const area = hist[i] * width;
        maxArea = Math.max(maxArea, area);
    }

    return maxArea;
}

// Driver code
const hist = [60, 20, 50, 40, 10, 50, 60];
console.log(getMaxArea(hist));