题目
分析
每次我们移动到数组中的一个新的位置 ii,我们就将当前单调栈中所有对应值小于nums[i] 的下标弹出单调栈。随后我们将位置 i入栈。
但是注意到只遍历一次序列是不够的
一个朴素的思想是,我们可以把这个循环数组「拉直」,即复制该序列的前 n-1个元素拼接在原序列的后面。这样我们就可以将这个新序列当作普通序列,用上文的方法来处理。
而在本题中,我们不需要显性地将该循环数组「拉直」,而只需要在处理时对下标取模即可。
代码
class Solution {
public int[] nextGreaterElements(int[] nums) {
LinkedList<Integer> stack=new LinkedList<>();
int len=nums.length;
int[] res=new int[len];
Arrays.fill(res,-1);
stack.addLast(0);
for(int i=1;i<2*len-1;i++){
while(!stack.isEmpty()&&nums[stack.peekLast()]<nums[i%len]){
res[stack.removeLast()]=nums[i%len];
}
stack.addLast(i%len);
}
return res;
}
}
复杂度
时间复杂度: O(n),其中 n 是序列的长度。我们需要遍历该数组中每个元素最多 2 次,每个元素出栈与入栈的总次数也不超过 4 次。
空间复杂度: O(n),其中 n 是序列的长度。空间复杂度主要取决于栈的大小,栈的大小至多为 2n-1。