Data Structures and Algorithms (DSA)  

Maximum Visible People in a Line Using Monotonic Stack

Problem Statement

You are given an array arr[] where arr[i] represents the height of the i-th person standing in a line.

A person i can see another person j if:

  • arr[j] < arr[i]

  • There is no person between i and j whose height is greater than or equal to arr[i]

Each person can look in both directions (left and right).

Your task is to determine the maximum number of people visible to any person, including the person themselves.

Example

Input

arr = [6, 2, 5, 4, 5, 1, 6]

Output

6

Explanation

The first person (height = 6) can see:

6, 2, 5, 4, 5, 1

Total visible people:

6

including themselves.

Similarly, the last person can also see 6 people.

Hence, the answer is:

6

Understanding the Visibility Rule

Consider a person of height H.

While looking left or right:

  • They can see only people shorter than H.

  • As soon as a person with height greater than or equal to H appears, the view is blocked.

The blocking person is not visible because visibility requires:

height[j] < height[i]

Therefore, the visibility region ends just before the first greater-or-equal person.

Key Observation

For every person i, we need to know two boundaries.

Left Boundary

The nearest person on the left whose height is:

>= arr[i]

This is called the:

Previous Greater-or-Equal Element (PGE)

Right Boundary

The nearest person on the right whose height is:

>= arr[i]

This is called the:

Next Greater-or-Equal Element (NGE)

Why These Boundaries Matter

Suppose:

left[i]  = nearest greater-or-equal index on left
right[i] = nearest greater-or-equal index on right

Then every person between:

(left[i] + 1) and (right[i] - 1)

is shorter than arr[i].

Therefore, person i can see the entire range:

left[i] + 1 ... right[i] - 1

including themselves.

Thus:

visibleCount = right[i] - left[i] - 1

Dry Run

Consider:

arr = [6, 2, 5, 4, 5, 1, 6]

First Person

Height:

6

Nearest greater-or-equal on the left:

None
left = -1

Nearest greater-or-equal on the right:

Index 6 (height = 6)
right = 6

Visible count:

6 - (-1) - 1 = 6

Visible people:

[6, 2, 5, 4, 5, 1]

Total:

6

Brute Force Approach

For each person:

  1. Move left until the view is blocked.

  2. Move right until the view is blocked.

  3. Count visible people.

Complexity

O(n²)

This exceeds the expected complexity for large inputs.

Optimized Approach Using Monotonic Stack

The problem can be transformed into:

  • Finding Previous Greater-or-Equal Elements.

  • Finding Next Greater-or-Equal Elements.

Both can be computed efficiently using a monotonic decreasing stack.

Step 1: Find Previous Greater-or-Equal

Maintain a stack of indices.

For every index i:

while (!st.empty() && arr[st.top()] < arr[i])
    st.pop();

left[i] = st.empty() ? -1 : st.top();

st.push(i);

After removing all smaller heights:

  • The stack top becomes the nearest greater-or-equal element on the left.

  • If the stack is empty, no such element exists.

Step 2: Find Next Greater-or-Equal

Traverse from right to left.

Again, remove all smaller elements:

while (!st.empty() && arr[st.top()] < arr[i])
    st.pop();

right[i] = st.empty() ? n : st.top();

st.push(i);

After processing:

  • The stack top represents the nearest greater-or-equal element on the right.

  • If none exists, use n.

Step 3: Calculate Visibility

For each person:

visible = right[i] - left[i] - 1

Track the maximum value among all people.

Why Monotonic Stack Works

The stack always maintains heights in decreasing order.

Whenever a taller person appears:

Smaller heights lose their usefulness

because they can no longer serve as the nearest greater-or-equal boundary for future elements.

Therefore, they are permanently removed.

Each index:

  • Is pushed into the stack once.

  • Is popped from the stack at most once.

This guarantees linear complexity.

C++ Solution

class Solution {
public:
    int maxPeople(vector<int> &arr) {

        int n = arr.size();

        vector<int> left(n), right(n);

        stack<int> st;

        // Previous Greater-or-Equal
        for(int i = 0; i < n; i++) {

            while(!st.empty() &&
                  arr[st.top()] < arr[i])
                st.pop();

            left[i] = st.empty() ? -1 : st.top();

            st.push(i);
        }

        while(!st.empty())
            st.pop();

        // Next Greater-or-Equal
        for(int i = n - 1; i >= 0; i--) {

            while(!st.empty() &&
                  arr[st.top()] < arr[i])
                st.pop();

            right[i] = st.empty() ? n : st.top();

            st.push(i);
        }

        int ans = 0;

        for(int i = 0; i < n; i++) {

            ans = max(ans,
                      right[i] - left[i] - 1);
        }

        return ans;
    }
};

Complexity Analysis

Time Complexity

Each index is pushed and popped at most once.

O(n)

Space Complexity

The arrays:

left[]
right[]

and the stack require:

O(n)

extra space.

Interview Pattern Recognition

Whenever a problem contains phrases such as:

  • Nearest taller person

  • Visibility blocked by height

  • First greater element

  • Previous greater element

  • Next greater element

  • Skyline problems

Think immediately of:

Monotonic Stack

This pattern appears frequently in interview questions, including:

  • Next Greater Element

  • Stock Span

  • Largest Rectangle in Histogram

  • Daily Temperatures

  • Buildings With Ocean View

  • Visibility Problems

Why This Solution Is Efficient

Instead of checking visibility for every pair of people, we identify the nearest blocking person on both sides. Once these boundaries are known, the visible range can be calculated directly using a simple formula. Monotonic stacks make it possible to find these boundaries in linear time.

Key Takeaway

The crucial insight is that a person's visible region is bounded by the nearest person on both sides whose height is greater than or equal to theirs. Once the problem is transformed into finding Previous and Next Greater-or-Equal Elements, a Monotonic Stack provides an elegant and efficient O(n) solution.

Summary

To determine the maximum number of visible people, find the nearest greater-or-equal person on the left and right for every individual. These boundaries define the entire visibility range. Using a monotonic decreasing stack, both boundaries can be computed in linear time, resulting in an overall complexity of O(n) with O(n) extra space. This problem is a classic application of the Previous Greater Element and Next Greater Element patterns.