线段树;84柱状图中最大的矩形;44. 通配符匹配

线段树

用处:给定数组v(n),求数组某区间[i,j]内的最大值(下标)/最小值(下标)/和

struct SegTreeNode
{
    int   le,ri;  //区间左右值,数组[le,ri],le和ri对应数组v的下标
    Node   *left;
    Node   *right;    
    //以上四个参数是必须的,下面可以根据需要增加自定义参数
    int sum;//sum=v[le]+...+v[ri]
    int max;//max=max(v[le],...,v[ri])
    int minIndex;//v[minIndex]=min(v[le],...,v[ri])
    SegTreeNode(int le,int ri) : le(le),ri(ri), left(NULL), right(NULL){}
};
SegTreeNode  *SegTreeBuild(vector<int>& v, int le ,int ri) {
    if(le>ri)return nullptr;    

    SegTreeNode   *root = new SegTreeNode(le,ri);
    
    if(le==ri){root->sum=v[le],root->max=v[le],root->minIndex=le;}//叶子节点
    else{    
        int  mid = (ri +le) >>1;
        root->left = SegTreeBuild(v, le , mid ) ;
        root->right = SegTreeBuild(v, mid+1  , ri ) ; 
        root->max=max(root->left->max,root->right->max);//更新max
        root->sum=root->left->sum+root->right->sum;//更新sum
        root->minIndex=v[root->left->minIndex]>v[root->right->minIndex]?root->right->minIndex:root->left->minIndex;//更新minIndex
    }
    return root; 
}
void   addValue(SegTreeNode  *root , int  addIndex , int  addValue)//v[addIndex]+=addValue
{
    if(root->le==root->ri&&root->le==addIndex){root->max+=addValue,root->sum+=addValue;}
    else{
        int mid=(root->le+root->ri)>>1;
        if(addIndex>=mid) addValue(root->right,addIndex,addValue);
        else addValue(root->left,addIndex,addValue);
        root->max=max(root->left->max,root->right->max);//更新max
        root->sum=root->left->sum+root->right->sum;//更新sum  
        root->minIndex=v[root->left->minIndex]>v[root->right->minIndex]?root->right->minIndex:root->left->minIndex;//更新minIndex      
    }
}
int getSum(SegTreeNode* root,int le,int ri){
    if(root->le==le&&root->root->ri==ri)return root->sum;    
    int mid=(root->le+root->ri)>>1;
    if(ri<=mid)return sum(root->left,le,ri);
    else if(le>mid)return sum(root->right,le,ri);
    else return sum(root->left,le,mid)+sum(root->right,mid+1,ri);//+ 
}
int getMax(SegTreeNode* root,int le,int ri){
    if(root->le==le&&root->root->ri==ri)return root->max;    
    int mid=(root->le+root->ri)>>1;
    if(ri<=mid)return max(root->left,le,ri);
    else if(le>mid)return max(root->right,le,ri);
    else return max(max(root->left,le,mid),max(root->right,mid+1,ri));//max(a,b)    
}
int getMinIndex(vector<int>& v,SegTreeNode* root,int le,int ri){//v
    if(root->le==le&&root->ri==ri)return root->minIndex;
    int mid=(root->le+root->ri)>>1;
    if(ri<=mid)return getMinIndex(v,root->left,le,ri);
    else if(le>mid)return getMinIndex(v,root->right,le,ri);
    else {
        int leftMinIndex=getMinIndex(v,root->left,le,mid);
        int rightMinIndex=getMinIndex(v,root->right,mid+1,ri);
        return v[leftMinIndex]>v[rightMinIndex]?rightMinIndex:leftMinIndex;//
    }
}

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

输入: [2,1,5,6,2,3] 输出: 10

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        //分治
        if(heights.size()==0)return 0;
        if(heights.size()==1)return heights[0];
        return helper(heights,0,heights.size()-1);
    }
    int helper(vector<int>& v,int le,int ri){
        if(le>ri)return 0;
        if(le==ri)return v[le];
        int minIndex=le;
        for(int i=le+1;i<=ri;++i)
            if(v[minIndex]>v[i])
                minIndex=i;
        int maxS=minIndex==le?0:helper(v,le,minIndex-1);
        int rBig=minIndex+1;
        while(rBig<=ri&&v[rBig]==v[minIndex])
            ++rBig;
        maxS=rBig>ri?maxS:max(maxS,helper(v,rBig,ri));   
        return max(maxS,v[minIndex]*(ri-le+1)); 
    }
};

线段树方法
 

class Solution {
public:
    struct SegTreeNode{
        int le,ri;
        SegTreeNode *left,*right;
        int minIndex;//数组下标,vec[minIndex]才是最小值
        SegTreeNode(int le,int ri):le(le),ri(ri),left(nullptr),right(nullptr){}
    };
    int largestRectangleArea(vector<int>& heights) {
        //分治
        if(heights.size()==0)return 0;
        if(heights.size()==1)return heights[0];
        SegTreeNode* root=SegTreeBuild(heights,0,heights.size()-1);
        return getMax(heights,root,0,heights.size()-1);
    }
    SegTreeNode* SegTreeBuild(vector<int>& v,int le,int ri){
        if(le>ri)return nullptr;
        SegTreeNode* root=new SegTreeNode(le,ri);
        if(le==ri)
            root->minIndex=le;
        else{
            int mid=(le+ri)>>1;
            root->left=SegTreeBuild(v,le,mid);
            root->right=SegTreeBuild(v,mid+1,ri);
            root->minIndex=v[root->left->minIndex]>v[root->right->minIndex]?root->right->minIndex:root->left->minIndex;
        }
        return root;
    }
    int getMin(vector<int>& v,SegTreeNode* root,int le,int ri){
        if(root->le==le&&root->ri==ri)return root->minIndex;
        int mid=(root->le+root->ri)>>1;
        if(ri<=mid)return getMin(v,root->left,le,ri);
        else if(le>mid)return getMin(v,root->right,le,ri);
        else {
            int leftMinIndex=getMin(v,root->left,le,mid);
            int rightMinIndex=getMin(v,root->right,mid+1,ri);
            return v[leftMinIndex]>v[rightMinIndex]?rightMinIndex:leftMinIndex;
        }
    }
    int getMax(vector<int>& v,SegTreeNode* root,int le,int ri){
        if(le>ri)return 0;//
        if(le==ri)return v[le];
        int minIndex=getMin(v,root,le,ri);
        int mid=(le+ri)>>1;
        int leftMax=getMax(v,root,le,minIndex-1);
        int rightMax=getMax(v,root,minIndex+1,ri);
        return max((ri-le+1)*v[minIndex],max(leftMax,rightMax));
    }
};
class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        //递增栈
        if(heights.size()==0)return 0;
        if(heights.size()==1)return heights[0];
        stack<int> s;
        s.push(0);
        vector<int> len(heights.size(),-1);
        int i=1;
        int maxS=0;
        while(s.size()||i<heights.size()){
            if(s.size()==0||i<heights.size()&&heights[i]>=heights[s.top()])
                s.push(i++);
            else{
                len[s.top()]+=i-s.top();
                s.pop();                
            }
        }
        s.push(heights.size()-1);
        i=heights.size()-2;
        while(s.size()||i>=0){
            if(s.size()==0||i>=0&&heights[i]>=heights[s.top()])
                s.push(i--);
            else{
                len[s.top()]+=s.top()-i;
                s.pop();                
            }
        }
        for(int j=0;j<len.size();++j)
            maxS=max(maxS,len[j]*heights[j]);
        return maxS;
    }
   
};

 

给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配。

'?' 可以匹配任何单个字符。
'*' 可以匹配任意字符串(包括空字符串)。


两个字符串完全匹配才算匹配成功。

说明:


    s 可能为空,且只包含从 a-z 的小写字母。
    p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *。


示例 1:

输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串。

示例 2:

输入:
s = "aa"
p = "*"
输出: true
解释: '*' 可以匹配任意字符串。


示例 3:

输入:
s = "cb"
p = "?a"
输出: false
解释: '?' 可以匹配 'c', 但第二个 'a' 无法匹配 'b'。


示例 4:

输入:
s = "adceb"
p = "*a*b"
输出: true
解释: 第一个 '*' 可以匹配空字符串, 第二个 '*' 可以匹配字符串 "dce".


示例 5:

输入:
s = "acdcb"
p = "a*c?b"
输出: false

vector<vector<int>> dp(m + 1, vector<int>(n + 1));
if (p[j - 1] == '*')    dp[i][j] = dp[i][j - 1] | dp[i - 1][j];
else if (p[j - 1] == '?' || s[i - 1] == p[j - 1])    dp[i][j] = dp[i - 1][j - 1];
class Solution {
//二维动态规划
public:
    bool isMatch(string s, string p) {
        int m = s.size();
        int n = p.size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));
        dp[0][0] = true;
        for (int i = 1; i <= n&&p[i - 1] == '*'; ++i)
                dp[0][i] = true;
        for (int i = 1; i <= m; ++i) 
            for (int j = 1; j <= n; ++j) 
                if (p[j - 1] == '*') 
                    dp[i][j] = dp[i][j - 1] | dp[i - 1][j];
                else if (p[j - 1] == '?' || s[i - 1] == p[j - 1])
                    dp[i][j] = dp[i - 1][j - 1];
        return dp[m][n];
    }
};

 

class Solution {//一维动态规划
public:
    bool isMatch(string s, string p) {
        int sLen=s.size(),pLen=p.size();
        vector<bool>dp(pLen+1,false);
        dp[0]=true;
        for(int i=1;i<=pLen&&p[i-1]=='*';++i)
            dp[i]=true;
        for(int i=1;i<=sLen;++i){            
            bool leftUp=dp[0];//leftUp和dp[0]的顺序易错
            dp[0]=false;//
            for(int j=1;j<=pLen;++j){
                bool curUp=dp[j];//
                if(p[j-1]=='*')
                    dp[j]=dp[j]||dp[j-1];
                else if(s[i-1]==p[j-1]||p[j-1]=='?')
                    dp[j]=leftUp;
                else dp[j]=false;//易漏掉
                leftUp=curUp;//
            }               
        }
        return dp[pLen];
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值