题目:
小Q在周末的时候和他的小伙伴来到大城市逛街,一条步行街上有很多高楼,共有n座高楼排成一行。
小Q从第一栋一直走到了最后一栋,小Q从来都没有见到这么多的楼,所以他想知道他在每栋楼的位置处能看到多少栋楼呢?(当前面的楼的高度大于等于后面的楼时,后面的楼将被挡住)
示例1
输入
[5,3,8,3,2,5]
输出
[3,3,5,4,4,4]
说明
当小Q处于位置3时,他可以向前看到位置2,1处的楼,向后看到位置4,6处的楼,加上第3栋楼,共可看到5栋楼。当小Q处于位置4时,他可以向前看到位置3处的楼,向后看到位置5,6处的楼,加上第4栋楼,共可看到4栋楼。
备注:
输入为一个数组,表示每一栋楼的高度w[i]
1<=数组长度<=100000;
1<=wi<=100000;
思路:
最直接也就是暴力遍历的方式就是直接在每一个位置都遍历整个数组。当然这必然会超出时间限制。那么要优化就要找到冗余成分。这道题的冗余成分就在于每一个元素的单个方向看过去,能够看到的楼必然曾递增趋势。那么在遍历过程保存递增楼层而消去中间段冗余的楼层就是需要做的优化步骤。不然在每一步遍历时,都会遍历判断是否可取。
这道题借鉴了某些大佬的想法。使用单调栈来解。
分两步,分别计算从右往左看和从左往右看的情况。
1.
从右往左看,那么保留递减趋势的楼层,也就是说,一开始,栈空,当我们遍历第一个楼层,第二个楼层向左看必然能看到,故而第一个楼层压入栈,此时第二个楼层往左看能看到的数量就是栈的大小,即1。遍历第二个楼层时,若第二个楼层比第一个楼层高,那么从第三个楼层开始,所有楼层都看不到第一个楼层了,那么就需要先弹出栈元素,再压入第二个楼层,若第二个楼层比第一个楼层低,那么这种递减趋势,第三个楼层往左看时都可以看到,也就是说,直接把第二个楼层压入栈,那么此时第三个楼层往左能看到的数量就是栈的大小,即2。依次类推,当遍历到第i个楼层时,若第i个楼层比栈顶元素的楼层高,那么就需要依次弹出比第i个楼层低或相等的楼层,然后在压入第i个楼层。此时第i+1个楼层往左看的数量也就确定了。
2.
从左往右看,与1同理,只要从数组后面往前遍历即可。
代码:
class Solution {