算法刷题记录 Day51
Date: 2024.04.19
lc 42. 接雨水
// 单调栈
class Solution {
public:
int trap(vector<int>& height) {
// 思路2:单调栈。当有个元素要入栈时。若该元素小于等于栈顶,则直接入栈;
// 若该元素大于栈顶,则出栈。出栈后的新的栈顶,就是该出栈元素的左侧最大值。
// (当前索引-新栈顶索引-1) * (min(左,右)-当前), 即为累计的雨水;
// 若出栈后无元素,则该元素自身为最大值,不统计该出栈值接了多少雨水。
int n = height.size();
int cur_idx = 0;
stack<int> st; // 存放单调栈的索引;
int sum = 0;
while(cur_idx < n){
while(!st.empty() && height[cur_idx] >= height[st.top()]){
int cur_pop_idx = st.top();
st.pop();
if(st.empty()){ //若出栈一个值后栈空,则该值自身为最大值,不累加雨水
}
else{
// cout<<(min(height[cur_idx], height[st.top()]) - height[cur_pop_idx]) * (cur_idx-st.top()-1))<<endl;
// cout<<"当前索引:"<<cur_pop_idx<<endl;
// cout<<"前一索引:"<<st.top()<<endl;
// cout<<"后一索引:"<<st.top()<<endl;
// cout<<"当前累加值:("<<min(height[cur_idx], height[st.top()])<<" - "<<height[cur_pop_idx]<< ") * "<<(cur_idx-st.top()-1)<<endl;
sum += (min(height[cur_idx], height[st.top()]) - height[cur_pop_idx]) * (cur_idx-st.top()-1);
}
}
st.push(cur_idx);
cur_idx++;
}
return sum;
}
};
// 双指针
class Solution {
public:
int trap(vector<int>& height) {
// 对于每个柱子(除头尾),能够接水的量是其左侧和右侧最大值中的较小值。
// 因此,使用双指针,遍历两次数组,获取每个位置的左侧最大值和右侧最大值。
// 再遍历一次数组,计算每个位置能接的雨水量并累计。
int n = height.size();
vector<int> leftHeight(n, 0);
vector<int> rightHeight(n, 0);
int left_max = height[0];
for(int i=1; i<n; i++){
leftHeight[i] = left_max;
left_max = max(left_max, height[i]);
}
int right_max = height[n-1];
for(int i=n-2; i>=0; i--){
rightHeight[i] = right_max;
right_max = max(right_max, height[i]);
}
int sum = 0;
for(int i=1; i<n-1; i++){
sum += max(min(leftHeight[i], rightHeight[i]) - height[i], 0);
}
return sum;
}
};
lc 503. 下一个更大元素II
class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
// 相当于把两个数组相连后进行处理。
vector<int> next(nums.size(), -1);
int cur_idx = 0;
stack<int> st;
while(cur_idx < 2*nums.size()){
int tmp_idx = cur_idx % nums.size();
while(!st.empty() && nums[tmp_idx] > nums[st.top()]){
if(next[st.top()] == -1){
next[st.top()] = nums[tmp_idx];
}
st.pop();
}
st.push(tmp_idx);
cur_idx++;
}
return next;
}
};