4.3 下一个更大元素II【503】
4.3.1 题目描述
4.3.2 方法一:单调栈 + 循环数组
思路及算法
我们可以使用单调栈解决本题。单调栈中保存的是下标,从栈底到栈顶的下标在数组 nums \textit{nums} nums 中对应的值是单调不升的。
每次我们移动到数组中的一个新的位置 i,我们就将当前单调栈中所有对应值小于 nums [ i ] \textit{nums}[i] nums[i] 的下标弹出单调栈,这些值的下一个更大元素即为 nums [ i ] \textit{nums}[i] nums[i](证明很简单:如果有更靠前的更大元素,那么这些位置将被提前弹出栈)。随后我们将位置 i 入栈。
但是注意到只遍历一次序列是不够的,例如序列 [2,3,1],最后单调栈中将剩余 [3,1],其中元素 [1] 的下一个更大元素还是不知道的。
一个朴素的思想是,我们可以把这个循环数组「拉直」,即复制该序列的前 n−1 个元素拼接在原序列的后面。这样我们就可以将这个新序列当作普通序列,用上文的方法来处理。
而在本题中,我们不需要显性地将该循环数组「拉直」,而只需要在处理时对下标取模即可。
代码
class Solution {
public int[] nextGreaterElements(int[] nums) {
int n = nums.length;
int[] ret = new int[n];
Arrays.fill(ret, -1);
Deque<Integer> stack = new LinkedList<Integer>();
for (int i = 0; i < n * 2 - 1; i++) {
while (!stack.isEmpty() && nums[stack.peek()] < nums[i % n]) {
ret[stack.pop()] = nums[i % n];
}
stack.push(i % n);
}
return ret;
}
}
复杂度分析
- 时间复杂度: O(n),其中 n 是序列的长度。我们需要遍历该数组中每个元素最多 2 次,每个元素出栈与入栈的总次数也不超过 4 次。
- 空间复杂度: O(n),其中 n 是序列的长度。空间复杂度主要取决于栈的大小,栈的大小至多为 2n-1。
4.3.3 my answer—双层for循环
class Solution {
public int[] nextGreaterElements(int[] nums) {
int res[] = new int[nums.length];
int count = 0;
for(int i = 0;i<nums.length;i++){
boolean flag = false;
count = i + 1;
while(count%nums.length != i){
count = count%nums.length;
if(nums[count] > nums[i]){
res[i] = nums[count];
flag = true;
break;
}
count++;
}
if(flag == false) res[i] = -1;
}
return res;
}
}
复杂度分析
- 时间复杂度: O ( n 2 ) O(n^2) O(n2),其中 n 是序列的长度。
- 空间复杂度: O(n),其中 n 是序列的长度。