单调栈
从栈低到栈顶元素依次减小的单调栈
/* *单调栈:从栈低到栈顶元素依次减小,栈低元素最大 *解决问题:求左边离他最近比它大的数,右边离他最近比它大的数 */ #include <iostream> #include <stack> #include <vector> using namespace std; int main() { vector<int> arr{3,5,4,1,6,8}; stack<int> stack; for(int i=0;i<arr.size();++i) { //因为谁出栈,谁就是离它右边最近比他大的,它的下一个元素是左边离它最近比他大的 while(!stack.empty()&&arr.at(stack.top())<=arr.at(i)) { cout<<arr.at(stack.top())<<": right_max="<<arr.at(i)<<"\t"; stack.pop(); if(!stack.empty()) cout<<" left_max="<<arr.at(stack.top())<<endl; else cout<<" left_max=nullptr"<<endl; } stack.push(i); } while(!stack.empty()) { cout<<arr.at(stack.top())<<": right_max=nullptr"<<"\t"; stack.pop(); if(!stack.empty()) cout<<" left_max="<<arr.at(stack.top())<<endl; else cout<<" left_max=nullptr"<<endl; } return 0; }
从栈低到栈顶元素依次增大的单调栈
/* *单调栈:从低到顶依次增大,栈低元素最小 *解决问题:左边和右边离他最近比他小的元素 */ #include <iostream> #include <vector> #include <stack> using namespace std; int main() { vector<int> arr{3,5,4,1,6,8}; stack<int> stack; for(int i=0;i<arr.size();++i) { //因为谁出栈,谁就是离它右边最近比他小的,它的下一个元素是左边离它最近比他小的 while(!stack.empty()&&arr.at(stack.top())>=arr.at(i)) { cout<<arr.at(stack.top())<<": right_min="<<arr.at(i)<<"\t"; stack.pop(); if(!stack.empty()) cout<<" left_min="<<arr.at(stack.top())<<endl; else cout<<" left_min=nullptr"<<endl; } stack.push(i); } while(!stack.empty()) { cout<<arr.at(stack.top())<<": right_min=nullptr"<<"\t"; stack.pop(); if(!stack.empty()) cout<<" left_min="<<arr.at(stack.top())<<endl; else cout<<" left_min=nullptr"<<endl; } return 0; }
应用
/* *单调栈实例:最大子矩阵的大小 *1 0 1 1 *1 0 1 1 *1 0 1 1 */ #include <iostream> #include <vector> #include <stack> using namespace std; class MaxSubMatrix { public: int max_sub_matrix(const vector<vector<int> > &m); private: int max_sub_matrix_core(const vector<int> &m); }; int MaxSubMatrix::max_sub_matrix(const vector<vector<int> > &m) { if(m.empty()||m.size()<=0||m.at(0).size()<=0) return -1; int maxArea=0; vector<int> m1(m.at(0).size(),0); for(int i=0;i<m.size();++i) { for(int j=0;j<m.at(0).size();++j) m1.at(j)=m.at(i).at(j)==0?0:m1.at(j)+1; maxArea=max(maxArea,max_sub_matrix_core(m1)); } return maxArea; } int MaxSubMatrix::max_sub_matrix_core(const vector<int> &m) { if(m.empty()||m.size()<=0) return -1; //栈中的元素可以递增,遇到小的元素就结算当前栈中的面积 stack<int> stack; int maxArea=0; for(int i=0;i<m.size();++i) { //遇到比栈顶小的元素就结算面积 while(!stack.empty()&&m.at(i)<=m.at(stack.top())) { int h=stack.top(); stack.pop(); int left=stack.empty()?-1:stack.top(); maxArea=max(maxArea,(i-left-1)*m.at(h)); } stack.push(i); } while(!stack.empty()) { int h=stack.top(); stack.pop(); int left=stack.empty()?-1:stack.top(); int right=m.size(); maxArea=max(maxArea,(right-left-1)*m.at(h)); } return maxArea; } int main() { vector<vector<int> > v{{0,0,0,1,0},{1,0,1,1,1},{1,0,1,1,1},{1,1,1,1,1}}; MaxSubMatrix ms; cout<<ms.max_sub_matrix(v)<<endl; return 0; }