单调栈

  从栈低到栈顶元素依次减小的单调栈

/*
 *单调栈:从栈低到栈顶元素依次减小,栈低元素最大 
 *解决问题:求左边离他最近比它大的数,右边离他最近比它大的数 
 */
#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;
}

 

posted on 2019-03-16 22:55  tianzeng  阅读(126)  评论(0编辑  收藏  举报

导航