一、前言
参考文献:代码随想录;
今天的主题还是单调栈,主要思考方式判断怎么利用这个栈,来实现记录数据的问题;
二、下一个更大元素||
1、思路:
这个题目和昨天的温度问题如出一辙,只是多了一个回环数组而已,仅此而已,所以就可以扩充数组,或者遍历两遍;
单调栈在这里的作用还是做一个单调递增的单调栈,来存储下一个最大数字的下标;
2、整体代码如下:
class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
int n = nums.size();
vector<int> ans(n, -1);
if (n == 0) return ans;
stack<int> st;
st.push(0);
for (int i = 1; i < n * 2; i++) {
if (nums[i % n] < nums[st.top()]) {
st.push(i % n);
} else if (nums[i % n] == nums[st.top()]) {
st.push(i % n);
} else {
while (!st.empty() && nums[i % n] > nums[st.top()]) {
ans[st.top()] = nums[i % n];
st.pop();
}
st.push(i % n);
}
}
return ans;
}
};
三、接雨水
1、思路:
(1)我一开始的双指针思路如下:
int trap(vector<int>& height) {
int n = height.size();
if (n < 3) return 0;
int left;
for (int i = 0; i < n; i++) {
if (height[i] != 0) {
left = i;
break;
}
}
int right = left + 1;
int maxRain = 0;
int sum = 0;
while (left < n) {
if (right < n && height[right] < height[left]) {
sum += height[left] - height[right];
right++;
}
if (right < n && height[right] >= height[left] && right - left < 2) {
left = right;
right++;
}
if (right < n && height[right] >= height[left] && right - left >= 2) {
maxRain += sum;
sum = 0;
left = right;
right++;
}
if (right == n) {
sum = 0;
right = left + 2;
left++;
}
}
return maxRain;
}
我这个代码看似复杂,但是只考虑了一边的大小,如果右边的柱子比左边的柱子小,但是中间又有比右边柱子小的,那么无法得出答案;
所以我们需要顾及两边最矮的柱子来解决问题,代码如下:
int trap(vector<int>& height) {
int n = height.size();
if (n < 3) return 0;
int left = 0, right = n - 1;
int leftMax = 0, rightMax = 0;
int ans = 0;
// 很巧妙的双指针思路,通过不断维护左右两边最高的柱子
// 来优先判断先去计算哪一边,低的柱子先计算,高的柱子后计算;
while (left < right) {
// 判断哪个柱子高
if (height[left] < height[right]) {
// 判断是否能积水
if (height[left] >= leftMax) {
// 不能积水就放重置最高的柱子
leftMax = height[left];
} else {
// 能积,就做差
ans += leftMax - height[left];
}
left++;
} else {
// 相同的原理
if (height[right] >= rightMax) {
rightMax = height[right];
} else {
ans += rightMax - height[right];
}
right--;
}
}
return ans;
}
(2) 单调栈思路:
这个思路真的不得了,它主要是利用栈来存储横向的数据,然后通过单调栈来排列,找到第一个比他大的值,然后再计算下一个比他小的值,然后高度做差,就是h,水平做差就是w,相乘得到面积。之后就大概差不多这样了。
2、整体代码如下:
int trap(vector<int>& height) {
stack<int> st;
st.push(0);
int res = 0;
for (int i = 1; i < height.size(); i++) {
if (height[st.top()] == height[i]) {
st.push(i);
} else if (height[st.top()] > height[i]){
st.push(i);
} else {
while (!st.empty() && height[st.top()] < height[i]) {
int mid = st.top();
st.pop();
if (!st.empty()) {
// 记住,这是算面积
int h = min(height[st.top()], height[i]) - height[mid];
int w = i - st.top() - 1;
res += h * w;
}
}
st.push(i);
}
}
return res;
}
Study time 1.5h
Leave message:
A laugh can be a very powerful thing.
笑可以是一件很有力量的事。