[每日一题]单调栈求解1944.队列中可以看到的人数

什么时候使用单调栈

单调栈能很好的对一组元素的峰、谷进行筛选处理,遇到和峰谷相关的场景,可以考虑用单调栈算法。

单调栈使用中思路和注意实现:

  1. 确认方向(左->右? 右->左?)
  2. 确认栈类型(递增/递减单调栈)
  • 递增单调栈:大数为出栈触发点,小数出栈;最终栈内数据一定包含最大那个数。
  • 递减单调栈:小数为出栈触发点,大数出栈;最终栈内数据一定包含最小那个数
  1. 业务目标结果与栈的关系(与出栈元素

有关 ;与栈内残余数据有关)

  • 业务与逐个元素有关,一般选择与出栈元素有关。(如:矩形面积、接雨水)
  • 业务与序列最大/小元素有关,一般选择与残余数据关联。(如滑窗内最大值)
  1. 业务是与出栈数据/残余数据有关,数据找大/找小,决定了使用递增/递减单调栈。
    遇到单调栈解决问题的业务场景,先根据单调栈特点建业务模型:

业务和单调栈关联模型:注意

  • 选择关联合适的触发出栈点index、出栈元素index、出栈前、后元素index。
  • 如有需要,可以入栈时调整index、原始数据。(如:计算矩形面积案例)

相等元素处理策略:触发出栈处理、还是入栈处理。
残余数据处理策略:根据不同业务,考虑最终栈内残余单向元素是否需要出栈处理。

参考链接:
链接: 【算法】单调栈

题目:1944.队列中可以看到的人数
有 n 个人排成一个队列,从左到右 编号为 0 到 n - 1 。给你以一个整数数组 heights ,每个整数 互不相同,heights[i] 表示第 i 个人的高度。

一个人能 看到 他右边另一个人的条件是这两人之间的所有人都比他们两人 矮 。更正式的,第 i 个人能看到第 j 个人的条件是 i < j 且 min(heights[i], heights[j]) > max(heights[i+1], heights[i+2], …, heights[j-1]) 。

请你返回一个长度为 n 的数组 answer ,其中 answer[i] 是第 i 个人在他右侧队列中能 看到 的 人数 。

思路:对某个人来说,如果此人的右边都是更矮的,那么对此人的左边,最多只能看到此人,因为此人的右边都被挡住了
具体方法:从右往左遍历数组,与栈顶进行比较,若大于栈顶则一直弹出直到空或小于,再将遍历的数组元素放入栈中,中间弹出的元素即为右侧能看到的元素。

代码

class Solution {
public:
    vector<int> canSeePersonsCount(vector<int>& heights) {
        stack<int> temp;
        int n=heights.size();
        vector<int> result(n,0);
        for(int i=n-1;i>=0;i--){
            while(!temp.empty()&&temp.top()<heights[i]){
                result[i]++;
                temp.pop();
            }
            //栈不为空时,栈顶的元素比遍历到的大,可看到栈顶
            if(!temp.empty()){
                result[i]++;
            }
            temp.push(heights[i]);
        }
        return result;
    }
};
  • 17
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值