public int maxWidthRamp(int[] nums) {
/* 此方法思路正确,但超时
int n = nums.length;
Deque<Integer> stack;
int max = 0;
for (int i = 0; i < n; i++) {
stack = new LinkedList<>();
stack.push(nums[i]);
int j = i + 1;
while (j < n) {
stack.push(nums[j]);
if (nums[j] >= nums[i] && stack.size() > max) {
max = stack.size();
}
j++;
}
}
return max == 0 ? 0 : max - 1;
*/
/**
* 单调栈, 栈中存储的是从nums[0]开始的递减序列的下标,这些递减序列就是栈底
* 然后逆序遍历数组计算哪个坡度最宽即可。
*
* 这里有个问题就是:为什么栈中代表的数据就是栈底呢?
* 我们最后要求的最大的宽度坡一定是以这个序列中的某一个i为坡底的,我们反证一下:
* 假设存在某个元素位置k不存在于上面的递减序列中,且有最大宽度j-k,
* 这也就说明k位置的元素一定是小于k前面所有的元素的,否则就会有更长的宽度,
* 但是既然k小于前面所有的元素,那么k就一定会被加入到该递减序列中,
* 与假设矛盾,所以不存在k,解一定存在递减序列中
*
* 以 [6, 1, 8, 2, 0, 5] 为例,可以带入试验。
*/
int n = nums.length;
int max = 0;
Deque<Integer> stack = new LinkedList<>();
for (int i = 0; i < n; i++) {
if (stack.isEmpty() || nums[stack.peek()] > nums[i]) {
stack.push(i);
}
}
for (int i = n - 1; i >= 0; i--) {
while (!stack.isEmpty() && nums[stack.peek()] <= nums[i]) {
int pos = stack.poll();
max = Math.max(max,i - pos);
}
}
return max;
}