【leetcode】周赛194---(1)1486. 数组异或操作 (2)1487. 保证文件名唯一 (3)1488. 避免洪水泛滥 (4)1489. 找到最小生成树里的关键边和伪关键边MST

1486、给你两个整数,n 和 start 。

数组 nums 定义为:nums[i] = start + 2*i(下标从 0 开始)且 n == nums.length 。

请返回 nums 中所有元素按位异或(XOR)后得到的结果。

示例 1:

输入:n = 5, start = 0
输出:8
解释:数组 nums 为 [0, 2, 4, 6, 8],其中 (0 ^ 2 ^ 4 ^ 6 ^ 8) = 8 。
     "^" 为按位异或 XOR 运算符。

class Solution {
public:
    int xorOperation(int n, int start) {
        int ans=start;
        for(int i=1;i<n;i++)
            ans^=start+2*i;
        return ans;
    }
};

 结果:

执行用时:0 ms, 在所有 C++ 提交中击败了100.00% 的用户

内存消耗:5.9 MB, 在所有 C++ 提交中击败了100.00% 的用户

 

1487、给你一个长度为 n 的字符串数组 names 。你将会在文件系统中创建 n 个文件夹:在第 i 分钟,新建名为 names[i] 的文件夹。

由于两个文件 不能 共享相同的文件名,因此如果新建文件夹使用的文件名已经被占用,系统会以 (k) 的形式为新文件夹的文件名添加后缀,其中 k 是能保证文件名唯一的 最小正整数 。

返回长度为 n 的字符串数组,其中 ans[i] 是创建第 i 个文件夹时系统分配给该文件夹的实际名称。

示例 1:

输入:names = ["kaido","kaido(1)","kaido","kaido(1)"]
输出:["kaido","kaido(1)","kaido(2)","kaido(1)(1)"]
解释:注意,如果含后缀文件名被占用,那么系统也会按规则在名称后添加新的后缀 (k) 。

 map运用

class Solution {
public:
    vector<string> getFolderNames(vector<string>& names) {
        vector<string> ans;
        unordered_map<string,int> mp;
        for(int i=0;i<names.size();i++){
            string cn=names[i];
            while(mp.count(cn)>0){
                mp[names[i]]++;
                cn=names[i]+"("+to_string(mp[names[i]])+")";
            }
            mp.insert({cn,0});
            ans.push_back(cn);
        }
        return ans;
    }
};

结果:

执行用时:488 ms, 在所有 C++ 提交中击败了66.85% 的用户

内存消耗:66 MB, 在所有 C++ 提交中击败了100.00% 的用户

 

1488、你的国家有无数个湖泊,所有湖泊一开始都是空的。当第 n 个湖泊下雨的时候,如果第 n 个湖泊是空的,那么它就会装满水,否则这个湖泊会发生洪水。你的目标是避免任意一个湖泊发生洪水。

给你一个整数数组 rains ,其中:

    rains[i] > 0 表示第 i 天时,第 rains[i] 个湖泊会下雨。
    rains[i] == 0 表示第 i 天没有湖泊会下雨,你可以选择 一个 湖泊并 抽干 这个湖泊的水。

请返回一个数组 ans ,满足:

    ans.length == rains.length
    如果 rains[i] > 0 ,那么ans[i] == -1 。
    如果 rains[i] == 0 ,ans[i] 是你第 i 天选择抽干的湖泊。

如果有多种可行解,请返回它们中的 任意一个 。如果没办法阻止洪水,请返回一个 空的数组 。

请注意,如果你选择抽干一个装满水的湖泊,它会变成一个空的湖泊。但如果你选择抽干一个空的湖泊,那么将无事发生

示例 :

输入:rains = [1,2,0,0,2,1]
输出:[-1,-1,2,1,-1,-1]
解释:第一天后,装满水的湖泊包括 [1]
第二天后,装满水的湖泊包括 [1,2]
第三天后,我们抽干湖泊 2 。所以剩下装满水的湖泊包括 [1]
第四天后,我们抽干湖泊 1 。所以暂时没有装满水的湖泊了。
第五天后,装满水的湖泊包括 [2]。
第六天后,装满水的湖泊包括 [1,2]。
可以看出,这个方案下不会有洪水发生。同时, [-1,-1,1,2,-1,-1] 也是另一个可行的没有洪水的方案。

 分情况讨论,注意抽干湖泊的日期选择。

class Solution {
public:
    vector<int> avoidFlood(vector<int>& rains) {
        unordered_map<int,int> mp;//池子编号,下雨日期
        set<int> day;//晴天日期
        for(int i=0;i<rains.size();i++){
            if(rains[i]==0){//标记可用于抽干的日子
                day.insert(i);
            }else{//下雨
                if(mp.count(rains[i])){//该湖泊已经满
                    bool flag=false;
                    if(day.size()>0){//有晴天,且晴天在两次下雨之间
                        for(auto it:day){
                            if(it>mp[rains[i]]){
                                flag=true;
                                mp[rains[i]]=i;
                                rains[it]=rains[i];
                                day.erase(it);
                                break;
                            }
                        }
                    }
                    if(!flag) return{};
                }else mp[rains[i]]=i;
                rains[i]=-1;
            }
        }
        for(auto it:day) rains[it]=1;
        return rains;
    }
};

结果:

执行用时:832 ms, 在所有 C++ 提交中击败了42.16% 的用户

内存消耗:109.2 MB, 在所有 C++ 提交中击败了100.00% 的用户

 

MST最小生成树

1489、给你一个 n 个点的带权无向连通图,节点编号为 0 到 n-1 ,同时还有一个数组 edges ,其中 edges[i] = [fromi, toi, weighti] 表示在 fromi 和 toi 节点之间有一条带权无向边。最小生成树 (MST) 是给定图中边的一个子集,它连接了所有节点且没有环,而且这些边的权值和最小。

请你找到给定图中最小生成树的所有关键边和伪关键边。如果从图中删去某条边,会导致最小生成树的权值和增加,那么我们就说它是一条关键边。伪关键边则是可能会出现在某些最小生成树中但不会出现在所有最小生成树中的边。

请注意,你可以分别以任意顺序返回关键边的下标和伪关键边的下标。

输入:n = 5, edges = [[0,1,1],[1,2,1],[2,3,2],[0,3,2],[0,4,3],[3,4,3],[1,4,6]]
输出:[[0,1],[2,3,4,5]]
解释:上图描述了给定图。
下图是所有的最小生成树。

注意到第 0 条边和第 1 条边出现在了所有最小生成树中,所以它们是关键边,我们将这两个下标作为输出的第一个列表。
边 2,3,4 和 5 是所有 MST 的剩余边,所以它们是伪关键边。我们将它们作为输出的第二个列表。

 纯MST和附加条件的MST

// 做一次MST得到该权重:wmin
// 对每一边,强制去掉,做MST,若权重w1>wmin,则该边为关键边key
// 对每一边,强制加入,做MST,若权重w2==wmin && 不是关键边key,则为fake
int Tree[105];
struct E{
    int a,b,w,id;
};
bool cmp(E x,E y){
    return x.w<y.w;
}
int findRoot(int x){
    return Tree[x]==-1?x:Tree[x]=findRoot(Tree[x]);
}
int MST(int n,vector<E> e){
    int wmin=0;
    for(int i=0;i<n;i++){
        Tree[i]=-1;
    }
    for(auto i:e){
        int a=findRoot(i.a);
        int b=findRoot(i.b);
        if(a!=b){
            Tree[b]=a;
            wmin+=i.w;
        }
    }
    return wmin;
}
set<int> MST_findKey(int n,vector<E> e,int wmin){//强制去掉
    set<int> ans;
    for(int k=0;k<e.size();k++){
        int w1=0;
        for(int i=0;i<n;i++){
            Tree[i]=-1;
        }
        for(auto i:e){
            if(i.id==k) continue;
            int a=findRoot(i.a);
            int b=findRoot(i.b);
            if(a!=b){
                Tree[b]=a;
                w1+=i.w;
            }
        }
        //注意此处的条件,w1<wmin属于:去掉k边,无法构成生成树,所以是关键边。
        if(w1>wmin||w1<wmin) ans.insert(k);
    }
    return ans;
}
vector<int> MST_findfake(int n,vector<E> e,int wmin,set<int> key){
    vector<int> ans;
    for(int k=0;k<e.size();k++){
        for(int i=0;i<n;i++){
            Tree[i]=-1;
        }
        Tree[e[k].b]=e[k].a;
        int w2=e[k].w;
        for(auto i:e){
            int a=findRoot(i.a);
            int b=findRoot(i.b);
            if(a!=b){
                Tree[b]=a;
                w2+=i.w;
            }
        }
        if(w2==wmin && !key.count(e[k].id)) ans.push_back(e[k].id);
    }    
    return ans;
}
class Solution {
public:
    vector<vector<int>> findCriticalAndPseudoCriticalEdges(int n, vector<vector<int>>& edges) {
        vector<E> e;//边的id,权重
        for(int i=0;i<edges.size();i++){
            E t;
            t.a=edges[i][0];
            t.b=edges[i][1];
            t.w=edges[i][2];
            t.id=i;
            e.push_back(t);
        }
        sort(e.begin(),e.end(),cmp);
        int wmin=MST(n,e);
        set<int> key=MST_findKey(n,e,wmin);
        vector<int> fake=MST_findfake(n,e,wmin,key);
        vector<int> k;
        vector<vector<int>> ans;
        for(auto i:key){
            k.push_back(i);
        }
        ans.push_back(k);
        ans.push_back(fake);
        return ans;
    }
};

结果:

执行用时:88 ms, 在所有 C++ 提交中击败了72.83% 的用户

内存消耗:12.4 MB, 在所有 C++ 提交中击败了100.00% 的用户

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值