LeetCode - 第206场周赛

本文主要解析LeetCode第206场周赛的四道题目:暴力解决二进制矩阵中的特殊位置问题;通过构建完全图和边权统计不开心的朋友;应用Kruscal算法解决连接所有点的最小费用问题;以及探讨如何检查字符串是否可以通过排序子字符串得到另一个字符串。
摘要由CSDN通过智能技术生成

Rank

A. 二进制矩阵中的特殊位置

暴力求解.

class Solution {
public:
    int numSpecial(vector<vector<int>>& mat) {
        int n=mat.size();
        int m=mat[0].size();
        int ans=0;
        for(int i=0;i<n;++i){
            for(int j=0;j<m;++j){
                if(!mat[i][j]) continue;
                bool ok=true;
                for(int r=0;r<n;++r) if(r!=i && mat[r][j]) ok=false;
                for(int c=0;c<m;++c) if(c!=j && mat[i][c]) ok=false;
                if(ok) ++ans;
            }
        }
        return ans;
    }
};

B. 统计不开心的朋友

建立 n 个结点的完全图,边权为朋友之间的重要程度,然后对于每对 pair 中的每个人,再枚举所有其他 pair,检查是否会让此人不开心.

class Solution {
public:
    int g[505][505];

    int unhappyFriends(int n, vector<vector<int>>& preferences, vector<vector<int>>& pairs) {
        for(int u=0;u<n;++u){
            int cur=n-1;
            for(int j=0;j<n-1;++j){
                int v=preferences[u][j];
                g[u][v]=cur--;
            }
        }
        int ans=0;
        for(int i=0;i<n/2;++i){
            int x=pairs[i][0],y=pairs[i][1];
            for(int j=0;j<n/2;++j){
                if(j==i) continue;
                int u=pairs[j][0],v=pairs[j][1];
                if((g[x][u]>g[x][y] && g[u][x]>g[u][v]) || (g[x][v]>g[x][y] && g[v][x]>g[v][u]) ){
                    ++ans;
                    break;
                }
            }
            for(int j=0;j<n/2;++j){
                if(j==i) continue;
                int u=pairs[j][0],v=pairs[j][1];
                if((g[y][u]>g[y][x] && g[u][y]>g[u][v]) || (g[y][v]>g[y][x] && g[v][y]>g[v][u]) ){
                    ++ans;
                    break;
                }
            }
        }
        return ans;
    }
};

C. 连接所有点的最小费用

最小生成树裸题,kruscal 算法.

class Solution {
public:
    struct Edge{
        int u,v,w;
        Edge(int uu=0,int vv=0,int ww=0):u(uu),v(vv),w(ww){}
        bool operator<(const Edge& e)const{
            return w<e.w;
        }
    };

    int n,m,par[1005];
    vector<Edge> edges;

    int findst(int x){
        if(x==par[x]) return x;
        return par[x]=findst(par[x]);
    }

    int minCostConnectPoints(vector<vector<int>>& points) {
        n=points.size();
        for(int i=0;i<n;++i){
            for(int j=i+1;j<n;++j){
                int w=abs(points[i][0]-points[j][0])+abs(points[i][1]-points[j][1]);
                edges.push_back(Edge(i,j,w));
            }
        }
        m=edges.size();
        sort(edges.begin(),edges.end());
        for(int i=0;i<=n;++i) par[i]=i;

        int ans=0,cnt=0;
        for(int i=0;i<m && cnt<n-1;++i){
            int ru=findst(edges[i].u);
            int rv=findst(edges[i].v);
            if(ru!=rv){
                ans+=edges[i].w;
                par[ru]=rv;
                ++cnt;
            }
        }
        return ans;
    }
};

D. 检查字符串是否可以通过排序子字符串得到另一个字符串

CodeForces-1187D 的简化版,对长度为 2 的连续区间进行排序其实就相当于冒泡排序,可以将最小的元素移动到最前面同时保持其它元素的相对位置不发生改变.

回到这道题目中,从前向后依次遍历目标串 t,如果发现 s[i]!=t[i],那么就要在 i 之后找到一个最近的 j,使得 s[j]=t[i],这样就可以使用冒泡排序把 s[j] 交换到下标 i 的位置,但是有个前提那就是 s[i],s[i+1]...s[j-1] 当中一定不能有比 s[j] 更小的元素,否则是 s[j] 是无法移动到 i 位置的.

CodeForces-1187D 给出的是一个整数序列,数值不再局限为 [0,9],需要使用线段树维护区间最值来进行进一步处理.

class Solution {
public:
    bool isTransformable(string s, string t) {
        int len=s.size();
        queue<int> que[10];
        for(int i=0;i<len;++i) que[s[i]-'0'].push(i);
        for(int i=0;i<len;++i){
            int d=t[i]-'0';
            if(que[d].empty()){
                return false;
            }
            for(int j=0;j<d;++j){
                if(!que[j].empty() && que[j].front()<que[d].front()) return false;
            }
            que[d].pop();
        }
        return true;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值