这道题是经典的单调栈问题,一个人能看到右边的所有人,直到被一个比他高或相等的人挡住。

解题思路

从右向左遍历,维护一个单调递减栈(栈里存的是未找到右侧第一个更高元素的人的下标)。

对于当前位置 i:

· 可以看到的人数:在栈中弹出所有比自己矮的人,每弹出一个就能看到一个人
· 如果弹出后栈非空,说明还有一个比自己高(或等高)的人,也能看到,再加1
· 最后把自己压入栈中

举例:[10, 6, 8, 5, 11, 9]

· 从右看 9:没有人,栈空 → 看到 0 人,栈 [9]
· 看 11:弹出 9(看到1人),栈空,没有人比 11 高 → 总共 1 人,栈 [11]
· 看 5:没弹出,栈顶 11 比 5 高,能看到 11 → 1 人,栈 [11, 5]
· 看 8:弹出 5(看到1人),栈顶 11 比 8 高,能看到 11 → 总共 2 人,栈 [11, 8]
· 看 6:弹出无,栈顶 8 比 6 高 → 1 人,栈 [11, 8, 6]
· 看 10:弹出 6(1人),弹出 8(2人),栈顶 11 比 10 高(3人)→ 总共 3 人,栈 [11, 10]

Python3 代码

```python
class Solution:
    def canSeePersonsCount(self, heights: List[int]) -> List[int]:
        n = len(heights)
        ans = [0] * n
        stack = []  # 单调递减栈,存下标
        
        for i in range(n - 1, -1, -1):
            # 弹出所有比自己矮的,每弹出一个就能看到一个人
            while stack and heights[stack[-1]] < heights[i]:
                stack.pop()
                ans[i] += 1
            
            # 如果栈非空,说明还有一个比自己高或等高的,也能看到
            if stack:
                ans[i] += 1
            
            # 把自己压入栈
            stack.append(i)
        
        return ans
```

复杂度分析

· 时间复杂度:O(n),每个元素最多入栈一次、出栈一次
· 空间复杂度:O(n),栈的大小

关键点说明

步骤 说明
遍历顺序 从右向左,因为每个人只能看右边
弹出条件 heights[stack[-1]] < heights[i],严格小于才弹出(等高的会挡住视线)
栈顶可见 弹出所有比自己矮的之后,如果栈非空,栈顶那个人也能看到
单调性 栈内始终保持递减(从栈底到栈顶)

 

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐