Before attempting this problem, you should be comfortable with:
For each person in the queue, we want to count how many people they can see to their right. Person i can see person j if there's no one taller than both of them standing in between. We track the maximum height seen so far as we scan rightward. If the minimum of the current person's height and the person we're checking is greater than the max height between them, they can see each other.
i, initialize a counter and track the maximum height seen so far.j = i + 1 to n - 1):heights[i] and heights[j] is greater than the max height between them, increment cnt.heights[j].cnt for person i and return res.class Solution:
def canSeePersonsCount(self, heights: List[int]) -> List[int]:
n = len(heights)
res = []
for i in range(n):
maxi = cnt = 0
for j in range(i + 1, n):
if min(heights[i], heights[j]) > maxi:
cnt += 1
maxi = max(maxi, heights[j])
res.append(cnt)
return resA monotonic decreasing stack helps us efficiently find visibility relationships. As we iterate left to right, we pop people who are shorter than the current person since they can now see this taller person as their last visible person. The person remaining on top of the stack (if any) can also see the current person since nothing blocks their view.
res array with zeros and an empty stack to store indices.heights from left to right:heights[stack[-1]] < h, pop and increment their count (they can see the current person).res.class Solution:
def canSeePersonsCount(self, heights: List[int]) -> List[int]:
n = len(heights)
res = [0] * n
stack = []
for i, h in enumerate(heights):
while stack and heights[stack[-1]] < h:
res[stack.pop()] += 1
if stack:
res[stack[-1]] += 1
stack.append(i)
return resWe can also solve this by iterating from right to left. For each person, we count how many people they can see by popping shorter people from the stack (each popped person is visible). If someone taller remains on the stack after popping, that person is also visible since nothing blocks the view.
res array with zeros and an empty stack to store heights.heights from right to left:stack[-1] < heights[i], pop and increment res[i].res[i] by 1 (the first taller or equal person is visible).heights[i] onto the stack.res.class Solution:
def canSeePersonsCount(self, heights: List[int]) -> List[int]:
n = len(heights)
res = [0] * n
stack = []
for i in range(n - 1, -1, -1):
while stack and stack[-1] < heights[i]:
stack.pop()
res[i] += 1
if stack:
res[i] += 1
stack.append(heights[i])
return resThis problem requires a monotonic decreasing stack. Using an increasing stack or getting the comparison direction wrong leads to incorrect visibility counts. When iterating left-to-right, pop elements shorter than the current person; when iterating right-to-left, pop elements shorter than the current person as well.
When a taller person blocks the view, they are still visible to the current person. After popping all shorter people from the stack, if the stack is not empty, the person at the top is also visible. Forgetting to add 1 for this blocking person is a common mistake.
You can store either indices or heights on the stack, but you must be consistent. Storing indices allows you to update the result array directly but requires looking up heights. Storing heights simplifies comparisons but requires a different approach to update results.
Person i can see person j if there is no one between them who is taller than both. This is not the same as "no one taller than person j" or "no one taller than person i". The blocking condition depends on the minimum of the two heights being compared against the maximum height between them.