z
栈排序 单调栈 单调栈 是一种和单调队列类似的数据结构。单调队列主要用于解决滑动窗口问题,单调栈则主要用于 解决NGE问题 (Next Greater Element),也就是,对序列中每个元素,找到下一个比它大的元素。 (当然,“下一个”可以换成“上一个”,“比它大”也可以换成“比他小”,原理不变。)
这比单调队列还简单一点。我们维护一个栈,表示“待确定NGE的元素 ”,然后遍历序列。当我们碰上一个新元素,我们知道,越靠近栈顶的元素离新元素位置越近。所以不断比较新元素与栈顶,如果新元素比栈顶大,则可断定新元素就是栈顶的NGE,于是弹出栈顶并继续比较。直到新元素不比栈顶大,再将新元素压入栈。显然,这样形成的栈是单调递减的。
方法一:按行求
依次遍历每一行,思路比较简单,理解容易除了超时之外并无明显缺点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution {public : int trap (vector<int >& height) { int maxh = 0 ; for (auto &h : height)maxh = max (maxh,h); int len = height.size (); int water = 0 ; for (int h = maxh;h >= 0 ;h--){ int left = -1 ; for (int i = 0 ;i < len;i++){ if (height[i] >= h){ if (left != -1 )water += (i - left - 1 ); left = i; } } } return water; } };
方法二:按列求
遍历每一列,然后分别求出这一列两边最高的墙。找出较矮的一端,和当前列的高度比较,如果当前列高度更低说明可以装下雨水。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution {public : int trap (vector<int >& height) { int len = height.size (); vector<int >max_left (len,0 );vector<int >max_right (len,0 ); for (int i = 1 ;i < len;i++){ max_left[i] = max (max_left[i-1 ],height[i-1 ]); } for (int i = len - 2 ;i >= 0 ;i--){ max_right[i] = max (max_right[i+1 ],height[i+1 ]); } int water = 0 ; for (int i = 1 ;i < len - 1 ;i++){ int minl = min (max_left[i],max_right[i]); if (height[i] < minl)water += minl - height[i]; } return water; } };
方法三:按面积求
数学方法,这个方法放到高中卷子里我兴许能想的出来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution {public : int trap (vector<int >& height) { int len = height.size (); long long red = 0 ; int maxl = 0 ; for (int i = 0 ;i < len;i++){ maxl = max (maxl,height[i]); red += maxl; } long long blue = 0 ;long long sum = 0 ; maxl = 0 ; for (int j = len - 1 ;j >= 0 ;j--){ maxl = max (maxl,height[j]); blue += maxl; sum += height[j]; } return red + blue - maxl*len - sum; } };
方法四:单调栈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution {public : int trap (vector<int >& height) { stack<int >s; int size = height.size (); int water = 0 ; for (int right = 0 ;right < size;right++){ while (!s.empty () && height[right] > height[s.top ()]){ int bottom = s.top (); s.pop (); if (s.empty ())break ; int left = s.top (); int leftHeight = height[left]; int rightHeight = height[right]; int bottomHeight = height[bottom]; water += (right - left - 1 )*(min (leftHeight,rightHeight) - bottomHeight); } s.push (right); } return water; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution {public : int largestRectangleArea (vector<int >& heights) { int size = heights.size () + 2 ; vector<int >he (size,0 ); for (int i = 1 ;i < size - 1 ;i++)he[i] = heights[i-1 ]; stack<int >st; st.push (0 ); int maxa = 0 ; for (int i = 1 ;i < size;i++){ while (he[st.top ()] > he[i]){ int curh = he[st.top ()]; st.pop (); int left = st.top (); maxa = max (maxa,(i - left - 1 ) * curh); } st.push (i); } return maxa; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 class Solution {public : int largestRectangleArea (vector<int >& heights) { int size = heights.size () + 2 ; vector<int >he (size,0 ); for (int i = 1 ;i < size - 1 ;i++)he[i] = heights[i-1 ]; stack<int >st; st.push (0 ); int maxa = 0 ; for (int i = 1 ;i < size;i++){ while (he[st.top ()] > he[i]){ int curh = he[st.top ()]; st.pop (); int left = st.top (); maxa = max (maxa,(i - left - 1 ) * curh); } st.push (i); } return maxa; } int maximalRectangle (vector<vector<char >>& matrix) { int m = matrix.size (), n = matrix[0 ].size (); vector<vector<int >>heights (m,vector<int >(n,0 )); for (int i = 0 ;i < n;i++) if (matrix[0 ][i] == '1' )heights[0 ][i] = 1 ; for (int i = 1 ;i < m;i++){ for (int j = 0 ;j < n;j++){ if (matrix[i][j] == '1' &&matrix[i-1 ][j] == '1' ) heights[i][j] = heights[i-1 ][j] + 1 ; else if (matrix[i][j] == '1' ) heights[i][j] = 1 ; else heights[i][j] = 0 ; } } int maxa = 0 ; for (int i = 0 ;i < m;i++)maxa = max (maxa,largestRectangleArea (heights[i])); return maxa; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution {public : vector<int > dailyTemperatures (vector<int >& temperatures) { int size = temperatures.size (); stack<int >s; vector<int >results (size,0 ); for (int right = 0 ;right < size;right++){ int cnt = 0 ; while (!s.empty () && temperatures[s.top ()] < temperatures[right]){ results[s.top ()] = right - s.top (); s.pop (); if (s.empty ())break ; } s.push (right); } return results; } };