## Problem Statement

In the historic city of Technisia there are rectangular monuments made of stones. The monuments are placed on the ground in such a way that they all lie in one row. The width of each monument is one unit and the length may vary. The population of the city is growing and people need empty spaces to build houses and markets. The mayor decides to demolish the monuments and presents a demolition schedule.

You being a monument lover, would like to preserve the most of what can be preserved, hence you start finding a solution to save the largest area. Upon your request the mayor granted you permission to preserve a continuous rectangular shape out of the monument. You want to preserve the maximum area possible.

Here are the monuments

You can choose to protect any rectangular portion as shown below, but the aim is to save the one with largest area. Here are few options for you.

Clearly in the above image the the model with a = 21 is the logical choice to save. The task at hand is to write a program to find the maximum possible area which can be saved from demolition.

## Approach

Like most of the problem statements we can solve this using the brute force technique and many other ways.

#### Trivial Solution

Here is a simple algorithm for solving this:

- Start from the beginning of the array.
- For every element ai of the array
- Move to the right until you get an element smaller than a
_{i}or the end of the array. Let say the index of the element is k. - Move to the left until you get an element smaller than a
_{i}. Let say the index of the element is j. - The total area which can be saved is a
_{i}* (k-j)

- Move to the right until you get an element smaller than a

**Source Code**

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
private static void largetArea(int N, int[] A) { int max = Integer.MIN_VALUE; for (int i = 0; i < N; i++) { int j = i; int num = A[j]; int tempMax = 0; while (j < N && A[j] >= num) { tempMax += num; j++; } j = i - 1; while (j >= 0 && A[j] >= num) { tempMax += num; j--; } if (tempMax > max) max = tempMax; } System.out.println(max); } |

#### Analysis

The above algorithm runs in O(N^{2}) time because the outer loop runs for the length of the array and the inner loop runs till both the ends from one element.

Space required is constant because we do not use any extra space apart from few temporary variables

**A Recursive Solution**

While writing the above solution, I realized that the approach is similar to the one used in finding the diameter of a tree. Here is how:

- Find the smallest element in the array, say its a
_{i}. - Now recursively find the largest area to the left of a
_{i}. Say it A_{L} - Recursively find the largest area to the right of a
_{i}. Say it A_{R} - The largest area which can be saved is the maximum of A
_{L}, A_{R}or a_{i * length of the array.}

Here is a visual of how the recursion will take place.

- The first step divides the array into two chunk through the red block.
- The left and right are then divided through the green blocks on both the sides
- The third recursion step divides the remaining array through the blue block.

**Source Code**

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
private static int largestAreaRecursive(int[] A, int l, int r) { if( r < l) return 0; if(r == l) return A[r]; int min = l; for (int i = l; i < r; i++) { min = Math.min(A[i], A[min]) == A[i] ? i : min; } int left = largestAreaRecursive(A, l, min - 1); int right = largestAreaRecursive(A, min + 1, r); int total = A[min] * (r - l + 1); int max = Math.max(left, right); max = Math.max(max, total); return max; } |

#### Here is the github link for a working code

#### Analysis

The above algorithm runs in O(NlogN) time for the same reason as the diameter of a tree problem.

T(N) = T(N/2) + T(N/2) + constant;

T(N) = 2 * T(N/2) + cN

The solution to this recurrence is O(NlogN).

For prove you can check the post about merge sort. If you face any difficulty understanding the post, please let me know in the comments below.

**Side Note: **Can we do better? O(NlogN) is great to achieve. But can we improve this? May be a linear time algorithm. Stay connected for further updates on the same.