啊啊啊!!!看到题的瞬间就想到了单调栈,但是结果……方向考虑反了
分析可知,当前位置能看见的是遇见右边比当前位置更高的之前的所有的一个递增序列。
计算每个位置右侧满足的递增序列的长度
注:该方法无法通过时间限制。
时间复杂度:O( n 2 n^2 n2)
空间复杂度:O(n)
public int[] canSeePersonsCount(int[] heights) {
LinkedList<Integer> list=new LinkedList<>();
int n=heights.length;
int[] res=new int[n];
for(int i=0;i<n-1;i++){
int j=i+1;
for(;j<n;j++){
if(heights[j]>heights[i]){
res[i]=list.size()+1;
break;
}
if(!list.isEmpty()&&list.getFirst()>heights[j]){
continue;
}
list.addLast(heights[j]);
}
if(j==n){
res[i]=list.size();
}
list.clear();
}
return res;
}
分析图例可以发现,第 0个人可以看到的三个人的身高是严格递增的。通过分析是可以验证这个规律,如果满足 i<j,此时下标为 j 且靠后的人比下标为 i且靠前的人矮,那么下标为 j 的人无法被下标 i之前的人看到。根据这个规律,可以想到利用单调栈来解决这个问题。从队伍末尾开始,维护一个单调栈,从栈底到栈顶,身高严格递减。
时间复杂度:O(n)
空间复杂度:O(n)
public int[] canSeePersonsCount(int[] heights) {
Deque<Integer> stack=new LinkedList<>();
int n=heights.length;
int[] res=new int[n];
//从右到左维护单调减栈
for(int i=n-1;i>=0;i--){
int cur=heights[i];
while(!stack.isEmpty()&&stack.peek()<cur){
stack.pop();
res[i]++;
}
if(!stack.isEmpty()){
res[i]++;
}
stack.push(cur);
}
return res;
}
有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈😄~