# 503下一个更大元素II 变体:circular
自己写的 20min:基础款思路+for(int i=1;i<2*nums.size()-1;i++) for loop多走一次,帮最后一个元素再从头走完; 这种题写的时候要分清是idx还是value,比如我会忘记应该是nums[st.top()]<nums[idx] 而不是直接st.top()<nums[idx]. 随想录和我思路一样。
vector<int> nextGreaterElements(vector<int>& nums) {
stack<int> st;
vector<int> res(nums.size(),-1);
st.push(0);
for(int i=1;i<2*nums.size()-1;i++){
int idx=i<nums.size()?i:i-nums.size();
//int idx=i%nums.size(); also ok
if(nums[st.top()]>nums[idx]) st.push(idx);
else{
while(!st.empty() && nums[st.top()]<nums[idx]){
res[st.top()]=nums[idx];
st.pop();
}
st.push(idx);
}
}
return res;
}
#42 接雨水 Hard,可多种方法解,面试常考
方法有:双指针法即dp,单调栈法
第一个自己写出的hard!虽然我的ac code跑出来很慢:先求出和前面几个题一样的,右边第一个比自己大的,左边第一个比自己大的,两个vec
然后进一步处理,变成 right里面装 右边最大的(而不是右边第一个最大的),left里面装 从右往左,左边最大的(而不是第一个最大的)
然后left[i]和right[i]取小的那个,做为水的高度,vec[i]就是底的高度。
int trap(vector<int>& vec) {
vector<int> left(vec.size(),-1);
vector<int> right(vec.size(),-1);
stack<int> st;
//find first right larger
st.push(0);
for(int i=1;i<vec.size();i++){
if(vec[i]<=vec[st.top()]) st.push(i);
else{
while(!st.empty() && vec[st.top()]<vec[i]){
right[st.top()]=vec[i];
st.pop();
}
st.push(i);
}
}
//get right max
int max=right[right.size()-1];
for(int i=right.size()-2;i>=0;i--){
if(right[i]!=-1) {
max=std::max(max,right[i]);
right[i]=max;
//right[i]=std::max(right[i+1],right[i]);
}
}
//find first left larger
while(!st.empty()) st.pop();
st.push(vec.size()-1);
for(int i=vec.size()-2;i>=0;i--){
if(vec[i]<=vec[st.top()]) st.push(i);
else{
while(!st.empty() && vec[st.top()]<vec[i]){
left[st.top()]=vec[i];
st.pop();
}
st.push(i);
}
}
//get left max
max=left[0];
for(int i=1;i<left.size();i++){
if(left[i]!=-1){
left[i]=std::max(left[i-1],left[i]);
}
}
//cal res
int sum=0;
for(int i=0;i<vec.size();i++){
if(left[i]!=-1 && right[i]!=-1){
sum+=min(left[i],right[i])-vec[i];
}
}
return sum;
}
但是!我这个思路太搞笑了,太复杂了,单调栈没用到点上
这样跑起来快多了,思路也正常了。根本不用stack 。这也就是双指针法(这个也是dp方法)
int trap(vector<int>& vec) {
vector<int> left(vec.size(),-1);
vector<int> right(vec.size(),-1);
int max_right = 0;
for(int i = vec.size() - 1; i >= 0; i--) {
max_right = max(max_right, vec[i]);
right[i] = max_right;
}
int max_left = 0;
for(int i = 0; i < vec.size(); i++) {
max_left = max(max_left, vec[i]);
left[i] = max_left;
}
//cal res
int sum=0;
for(int i=0;i<vec.size();i++){
if(left[i]!=-1 && right[i]!=-1){
sum+=min(left[i],right[i])-vec[i];
}
}
return sum;
}
单调栈方法:
栈顶和栈顶的下一个元素以及要入栈的元素,三个元素来接水!
int trap(vector<int>& height) {
stack<int> st;
st.push(0);
int sum = 0;
for (int i = 1; i < height.size(); i++) {
if (height[i] < height[st.top()]) {
st.push(i);
} if (height[i] == height[st.top()]) {
//updatt, so we can use the right most pole
st.pop();
st.push(i);
} else {
while (!st.empty() && height[i] > height[st.top()]) {
int mid = st.top();//stack top
st.pop();
if (!st.empty()) {//stack top next
int h = min(height[st.top()], height[i])- height[mid];
int w = i - st.top() - 1;
//printf("h: %d, w: %d from %d -%d\n",h,w,i,st.top());
sum += h*w;
}
}
st.push(i);
}
}
return sum;
}