主要思路
1.假设两个指针i,j, i指向数组头部,j指向数组尾部,我们要做的就是使i尽可能小,j尽可能大时,满足j指向的元素大于等于i指向的元素,此时j-i即最大宽度。
2.所以我们从左往右遍历数组,利用单调栈,栈中存的是元素的下标,下标所对应的元素严格递减,最后栈顶元素就是最小元素。
3.最后我们从后往前遍历数组,如果大于等于当前栈顶所对应的元素,那么更新结果,并将栈顶元素出栈,重复此过程。
/*
根据题意需要找出最大宽,首先要求i < j,即i尽可能的小,j尽可能的大;
很容易想到i需要从左往右,j从右往左遍历数组。
进一步思考,看第二个条件A[i] <= A[j],那么我们让A[i]的值尽可能的小,
然后再从右往左遍历数组,挨个和A[i]比较,就可以得到答案。
到这里,主要的问题就是怎么让A[i]尽可能的小,可以想到利用单调递减栈:
1、正向扫描数组记录严格的单调递减A[i]的下标
2、反向扫描数组比较A[j]与栈顶元素A[s.top()]的值,如果满足条件,则弹出栈顶元素,不断循环直到栈为空
*/
class Solution {
public:
int maxWidthRamp(vector<int>& nums) {
int len = nums.size();
stack<int> dec_stk;//严格单调递减栈
//从左往右存严格递减元素,最后一个元素是最小的
for(int i = 0;i<len;++i) {
if(dec_stk.empty() || nums[i]<nums[dec_stk.top()]) {
dec_stk.push(i);//将下标存进去
}
}
//从右往左与栈顶元素比较,满足条件则出栈,不断更新最大宽度
int ans = 0;
for(int j = len-1;j>ans;--j) {//对j做了优化,j要是比ans小了,那么在继续减就没意义了,最大宽度已经找到了
while(!dec_stk.empty()&&nums[j]>=nums[dec_stk.top()]) {
ans = max(ans,j-dec_stk.top());
dec_stk.pop();
}
}
return ans;
}
};