黄钻9
A
题意:
牛牛从牛毕那里拿了一根长度为n的白木板,木板被等分成了n段(没有被切割,只是虚拟划分成了n段),其中有些段被牛毕用颜料染成了黑色。
牛牛非常不喜欢黑色,它找来了一桶清洗剂决定对木板进行清洗,但是牛牛发现自己的清洗剂最多只能清洗m段。
清洗完后,牛牛会把木板锯成纯色的几段。例如假设木板是 (黑黑黑白白白白黑黑黑 ),就会被锯成(黑黑黑)(白白白白)(黑黑黑)三段。
牛牛想知道,它足够聪明地清洗木板,能获得的纯白色木板的最大长度是多少。

输入:
给定n,m两个整数
和一个长度为n的数组a,为1表示白色,为0表示黑色

输出:
一行一个数字表示能获得的纯白色木板的最大长度是多少
思路:数组sum求前i段中黑色的段数,然后遍历一遍sum,找到黑色段数小于m且区间长度最大的区间。
代码:

class Solution {
public:
    /**
     * 
     * @param n int整型 
     * @param m int整型 
     * @param a int整型vector 
     * @return int整型
     */
    int sum[1000005];//如上所述
    int solve(int n, int m, vector<int>& a) {
        // write code here
        for(int i=0;i<a.size();i++){
            sum[i+1]=sum[i];
            if(a[i]==0)sum[i+1]++;
        }
        int ans=0,l=0,r=1;
        for(int i=1;i<=n;i++){
            while(l<=n&&sum[r]-sum[l]>m)l++;
            while(r<=n&&sum[r]-sum[l]<=m)r++;
            ans=max(ans,r-1-l);
        }
        return ans;
    }
};

B
题目
给定一棵有n个结点的二叉树的先序遍历与后序遍历序列,求其中序遍历序列。
若某节点只有一个子结点,则此处将其看作左儿子结点.
思路:看到题目就想直接将这棵二叉树构造出来,然后想半天没想起数据结构课咋讲的。不太明白的话还是直接复习数据结构吧。
代码:

class Solution {
public:
    /**
     * 返回所求中序序列
     * @param n int整型 二叉树节点数量
     * @param pre int整型vector 前序序列
     * @param suf int整型vector 后序序列
     * @return int整型vector
     */
    vector<int>v;
    int l[100005],r[100005],fa[100005];
    map<int,int>mp;
    void dfs(int u)
    {
        if(u==0)return;
        dfs(l[u]);
        v.push_back(u);
        dfs(r[u]);
    }
    vector<int> solve(int n, vector<int>& pre, vector<int>& suf) {
        // write code here
        for(int i=0;i<suf.size();i++)mp[suf[i]]=i;
        fa[0]=0;
        //根据序列构造树
        for(int i=0;i<pre.size()-1;i++){
            int u=pre[i],v=pre[i+1];
            if(mp[v]<mp[u]){
                l[u]=v;
                fa[v]=u;
            }else{
                while(mp[v]>mp[u])u=fa[u];
                r[u]=v;
                fa[v]=u;
            }
        }
        //再跑一遍树,确定中序序列
        dfs(pre[0]);
        return v;
    }
};

C
题意:

游戏是在一个N*N的网格图中进行的,图中的网格分为四种类型,0表示空地可以通过,1表示墙壁无法通过,2表示不仅可以通过,还可以在该格放置一个传送门,3表示有且仅有的唯一的固定传送门。
思路:看起来就是个模拟,实际上还是个模拟。直接暴力搜到达该点的最小步数,然后同时找到最近的2放置传送门用来更新最远的3(直接一步传送)。需要注意的是要从(0,0)出发搜一遍,然后从(N-1,N-1)出发搜一遍,看样例就知道两个起始点算出来的答案不一样,取决于2和3怎么放。
代码:

class Solution {
public:
    /**
     * 返回最终要输出的答案
     * @param N int整型 表示地图的大小
     * @param a int整型二维数组 地图的描述
     * @param aRowLen int a数组行数
     * @param aColLen int* a数组列数
     * @return int整型
     */
    int vis[550][550],x=0,y=0,temp,temp1,ans;
    void dis(int N,int** a,int sx,int sy)//从(sx,sy)出发
    {
        queue<pair<int,int>>q;
        q.push(make_pair(sx,sy));
        memset(vis,0x3f3f3f3f,sizeof(vis));
        temp=0x3f3f3f3,temp1=0x3f3f3f3f;
        vis[sx][sy]=0;
        while(!q.empty()){
            x=q.front().first,y=q.front().second;
            q.pop();
            if(a[x][y]==3&&temp+1<vis[x][y])vis[x][y]=temp+1;
            else if(a[x][y]==2&&vis[x][y]<temp)temp=vis[x][y];//因为最近的2一般出现在最远的3前面,如果不在,那也不用更新了
            //上下左右
            if(x-1>=0&&a[x-1][y]!=1&&vis[x][y]+1<vis[x-1][y]){
                q.push(make_pair(x-1,y));
                vis[x-1][y]=vis[x][y]+1;
            }
            if(y-1>=0&&a[x][y-1]!=1&&vis[x][y]+1<vis[x][y-1]){
                q.push(make_pair(x,y-1));
                vis[x][y-1]=vis[x][y]+1;
            }
            if(x+1<N&&a[x+1][y]!=1&&vis[x][y]+1<vis[x+1][y]){
                q.push(make_pair(x+1,y));
                vis[x+1][y]=vis[x][y]+1;
            }
            if(y+1<N&&a[x][y+1]!=1&&vis[x][y]+1<vis[x][y+1]){
                q.push(make_pair(x,y+1));
                vis[x][y+1]=vis[x][y]+1;
            }
        }
    }
    int solve(int N, int** a, int aRowLen, int* aColLen) {
        // write code here
        dis(N,a,0,0);
        ans=vis[N-1][N-1];
        dis(N,a,N-1,N-1);
        ans=min(ans,vis[0][0]);
        return ans;
    }
};