leetcode 周赛146

题目链接:https://leetcode-cn.com/contest/weekly-contest-146/

5130. 等价多米诺骨牌对的数量

排序一下,相邻判断相等,然后用C(n,2)计算一下。

class Solution {
    struct node
    {
        int u,v;
        bool operator <(const node& a)const
        {
            return u==a.u? v<a.v:u<a.u;
        }
    }p[40005];
public:
    int numEquivDominoPairs(vector<vector<int>>& dominoes) {
        for(int i=0;i<dominoes.size();i++)
        {
            vector<int> t=dominoes[i];
            p[i].u=t[0];
            p[i].v=t[1];
            if(p[i].u>p[i].v)
                swap(p[i].u,p[i].v);
        }
        sort(p,p+dominoes.size());
        int ans=0,s=1;
        for(int i=1;i<dominoes.size();i++)
        {
            if(p[i].u==p[i-1].u && p[i].v==p[i-1].v)
                s++;
            else
            {
                ans+=s*(s-1)/2;
                s=1;
            }
        }
        ans+=s*(s-1)/2;
        return ans;
    }
};

5132. 颜色交替的最短路径

bfs,记忆化一下。

class Solution {
    struct node
    {
        int step,u,col;
    }p;
public:
    vector<int> shortestAlternatingPaths(int n, vector<vector<int>>& red_edges, vector<vector<int>>& blue_edges) {
        queue<node> q;
        bool vis[405][2];
        memset(vis,0,sizeof vis);
        int inf = 0x3f3f3f3f;
        int dis[405][2];
        for(int i=0;i<n;i++)
            dis[i][0]=dis[i][1]=inf;
        p.step=p.u=p.col=0;
        q.push(p);
        p.col=1;
        q.push(p);
        while(!q.empty())
        {
            node top=q.front(); q.pop();
            if(vis[top.u][top.col]) continue;
            vis[top.u][top.col]=1;
            dis[top.u][top.col]=top.step;
            if(top.col==0)
            {
                for(vector<int> t:blue_edges)
                {
                    if(t[0]==top.u)
                    {
                        p.step=top.step+1;
                        p.u=t[1];
                        p.col=1;
                        q.push(p);
                    }
                }
            }
            else
            {
                for(vector<int> t:red_edges)
                {
                    if(t[0]==top.u)
                    {
                        p.step=top.step+1;
                        p.u=t[1];
                        p.col=0;
                        q.push(p);
                    }
                }
            }
        }
        vector<int> ans;
        for(int i=0;i<n;i++)
        {
            int minn=min(dis[i][0],dis[i][1]);
            ans.push_back(minn==inf?-1:minn);
        }
            
        return ans;
    }
};

5131. 叶值的最小代价生成树

分析题目,可以看出来就是一个石子合并题目,只不过计算规则变了。我们可以用一个maxx[i][j]维护区间(i,j)内的最大值。

class Solution {
public:
    int mctFromLeafValues(vector<int>& arr) {
        int n=arr.size();
        long long maxx[45][45];
        long long dp[45][45];
        long long inf=0x3f3f3f3f3f3fLL;
        for(int i=0;i<n;i++)
            maxx[i][i]=arr[i],dp[i][i]=0;  
        for(int i=1;i<n;i++)
        {
            for(int beg=0;beg<n-i;beg++)
            {
                int end=beg+i;
                maxx[beg][end]=max(maxx[beg][end-1],maxx[end][end]);
                dp[beg][end]=inf;
                for(int k=beg;k<end;k++)
                {
                    long long sub=0;
                    dp[beg][end]=min(dp[beg][end],dp[beg][k]+dp[k+1][end]+maxx[beg][k]*maxx[k+1][end]);
                }
            }
        }
        return dp[0][n-1];
    }
};

5133. 绝对值表达式的最大值

大力分类讨论。O(n)

以下i<j

1,arr1[i]<arr1[j] && arr2[i]<arr2[j]

我们可以合并为一个数组:dis[i]=arr1[i]+arr2[i]+i;

计算用后面的减去前面的,下标的影响为正,表达式值不变。

2,arr1[i]>arr1[j] && arr2[i]>arr2[j]

我们可以合并为一个数组:dis[i]=arr1[i]+arr2[i]-i;

计算用前面的减去后面的,下标的影响为负。

3,arr1[i]<arr1[j] && arr2[i]>arr2[j]

我们可以合并为一个数组:dis[i]=arr1[i]-arr2[i]+i;

计算用后面的减去前面的,下标的影响为正,表达式值不变。

4,arr1[i]>arr1[j] && arr2[i]<arr2[j]

我们可以合并为一个数组:dis[i]=arr1[i]-arr2[i]-i;

计算用前面的减去后面的,下标的影响为负。

计算dis差值时可以用前缀和和后缀和的思想,这样复杂度为On。

class Solution {
public:
    int maxAbsValExpr(vector<int>& arr1, vector<int>& arr2) {
        int MAXN = 40005;
        int n=arr1.size();
        int ans=0;
        int pre[MAXN],suf[MAXN];
        int dis[MAXN];
        for(int i=0;i<n;i++)
            dis[i]=arr1[i]+arr2[i]+i;
        pre[0]=dis[0];
        for(int i=1;i<n;i++)
            pre[i]=min(pre[i-1],dis[i]);
        suf[n-1]=dis[n-1];
        for(int i=n-2;i>=0;i--)
            suf[i]=max(suf[i+1],dis[i]);
        for(int i=0;i<n-1;i++)
            ans=max(ans,suf[i+1]-pre[i]);
        
        for(int i=0;i<n;i++)
            dis[i]=arr1[i]+arr2[i]-i;
        pre[0]=dis[0];
        for(int i=1;i<n;i++)
            pre[i]=max(pre[i-1],dis[i]);
        suf[n-1]=dis[n-1];
        for(int i=n-2;i>=0;i--)
            suf[i]=min(suf[i+1],dis[i]);
        for(int i=0;i<n-1;i++)
            ans=max(ans,pre[i]-suf[i+1]);
        
        for(int i=0;i<n;i++)
            dis[i]=arr1[i]-arr2[i]+i;
        pre[0]=dis[0];
        for(int i=1;i<n;i++)
            pre[i]=min(pre[i-1],dis[i]);
        suf[n-1]=dis[n-1];
        for(int i=n-2;i>=0;i--)
            suf[i]=max(suf[i+1],dis[i]);
        for(int i=0;i<n-1;i++)
            ans=max(ans,suf[i+1]-pre[i]);
        
        for(int i=0;i<n;i++)
            dis[i]=arr1[i]-arr2[i]-i;
        pre[0]=dis[0];
        for(int i=1;i<n;i++)
            pre[i]=max(pre[i-1],dis[i]);
        suf[n-1]=dis[n-1];
        for(int i=n-2;i>=0;i--)
            suf[i]=min(suf[i+1],dis[i]);
        for(int i=0;i<n-1;i++)
            ans=max(ans,pre[i]-suf[i+1]);
        return ans;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值