1944. Visible People
Number of Visible People in a Queue
A very fun hard problem. I'll admit the math formula initially caught me off balance.
What Does It Mean to See Someone at your Right?
According to definition: in a queue of people,
for indices and with ,
person can see person only if everyone between them is shorter than both of them.
In math:
What the Formula Reveals
For any : if person is not taller than person ,
person and person will never satisfy that math formula above.
Person can't see person .
At this point, don't you feel monotonicity 😀?
Combined with a right-to-left traversal: when person is processed,
person comes next, and person comes later.
Person is immediately eliminated as a candidate that any left-side person could see.
Eliminating candidates in last-in-first-out order. A stack style.
The Mechanics
Pop Move 🍿
Each time person is processed, compare stack top with person .
As long as the person at stack top is shorter than person , pop this person off,
and increment person 's rightward visibility count by one.
Under this pop logic, everyone between the popped person and person is shorter than both.
When to stop popping? Stop when the person at stack top is not shorter than person .
Watch Out Details ㊙️
Once we reach the point where the person at stack top is not shorter than person ,
there's a subtle detail to handle carefully.
(1). First, the person at stack top can definitely be seen by person , regardless of whether they're taller or the same height.
Math formula from the start supports this. Increment person 's rightward visibility count by one.
(2). Here's the tricky part: if the person at stack top is taller than person ,
people to the left of person still have a chance to see this person at stack top,
since math formula can still be satisfied.
But if the person at stack top is the same height as person ,
no one to the left of person can see this person at stack top,
because math formula can no longer be satisfied.
So that equally tall stack top person must be popped immediately.
In short:
both cases we increment person 's rightward visibility count by one,
but only when the person at stack top equals person 's height do we also pop stack.
Don't mix them up. After handling these pops, push person onto stack.
- C++
- Python
#include <stack>
#include <vector>
using namespace std;
vector<int> countVisibilities(vector<int>& heights) // LeetCode Q.1944.
{
stack<int> stack; // A stack of heights.
vector<int> visibilities(heights.size(), 0);
for (int idx = heights.size() - 1; idx >= 0; idx--) {
int height = heights[idx];
while (!stack.empty() && stack.top() < height) {
stack.pop();
visibilities[idx]++;
}
if (!stack.empty()) {
visibilities[idx]++;
if (stack.top() == height)
stack.pop();
}
stack.push(height);
}
return visibilities;
}
def count_visibilities(heights: list[int]) -> list[int]: # LeetCode Q.1944.
stack = []
visibilities = [0] * len(heights)
for idx in range(len(heights) - 1, -1, -1): # Backward iteration.
height = heights[idx]
while stack and stack[-1] < height: # People on my left side can't see them.
stack.pop(-1)
visibilities[idx] += 1 # I can see unblocked shorter people.
if stack: # I can always see my next non-shorter person (if exists).
visibilities[idx] += 1
if stack[-1] == height: # People on my left side can't see this person.
stack.pop(-1)
stack.append(height)
return visibilities

Time complexity: — each person is pushed once and popped at most once.
Space complexity: — in the worst case, everyone is shorter than people to their right and stays in stack.