SWE · Coding

Meta 海景房:从右扫描与从左单调栈

海在右侧时,分别用后缀最大值和单调栈返回可见建筑下标。

题目重点:海在右侧时,分别用后缀最大值和单调栈返回可见建筑下标。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 练习海在数组右侧;建筑仅在高度严格大于右侧所有建筑时可见,同高也遮挡。输入可含负高度,输出下标从小到大。
  • 方向是合同的一部分,若海在左侧就镜像处理。建筑间距离不影响本题的高度遮挡判断;真实几何视角问题需要额外坐标。

解题路线

  1. 从右到左保留已看右侧的maximum。只有h>maximum时当前可见,记录下标并更新maximum;最后逆转输出恢复原顺序。
  2. 扫描不变式是maximum等于已处理后缀最大值,因此可见判断直接对应题意。用None初始化而非0,才能正确处理全部负高度和空数组。
  3. 若面试要求从左到右扫描,用下标栈保留尚未被遮挡的候选。当前高度≥栈顶高度时弹出栈顶,然后加入当前下标;同高必须弹出。
  4. 每个下标最多入栈与出栈一次,内层while总计O(N)。栈里的高度严格递减,其顺序天然是从左到右,结束时就是可见建筑。

手动走一遍

[4,2,3,1]可见[0,2,3];从左扫描遇3会移除2,遇1保留。对于[2,2]只有最右下标1可见;[-3,-2]也只有1可见。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

def ocean_view_from_right(heights):
    """Ocean right; a building needs strictly greater height than all to right."""
    maximum=None;visible=[]
    for i in range(len(heights)-1,-1,-1):
        if maximum is None or heights[i]>maximum:visible.append(i);maximum=heights[i]
    return visible[::-1]

def ocean_view_left_to_right(heights):
    """Same right-ocean contract, scanning opposite way via decreasing stack."""
    stack=[]
    for i,height in enumerate(heights):
        while stack and heights[stack[-1]]<=height:stack.pop()
        stack.append(i)
    return stack

复杂度

两种实现时间O(N)。右扫描除结果之外O(1)状态,结果逆转需要O(K)新列表;左扫描栈最坏O(N),最终栈即结果。若要求流式输出,左扫描早期候选可能被未来遮挡,不能立即确定。

易错点与追问

容易失分的边界

  • 忽略同高遮挡,使用<弹栈导致错误保留。
  • maximum初始化0,错误处理负高度。
  • 把输出高度与输出下标混淆,重复高度会丢失身份。

继续深挖

  • 如果海在两侧,分别计算两边可见集合并说明求并集还是交集。
  • 若建筑高度支持更新,用区间最大值结构判断某建筑是否可见;输出全部可见仍受输出量下界约束。
✓已复制微信号!