【刷爆LeetCode】七月算法集训(26)并查集

题目来源于知识星球—英雄算法联盟,七月算法集训专题

前言

跟随英雄算法联盟博主—英雄哪里出来,每天完成相应的算法练习,一个月后,必定会有所成长!
今天还是看题解的一天!


一、面试题 17.07.婴儿名字(中等)

1.题目描述

https://img-blog.csdnimg.cn/9228089a7fce408c9bef9d20774f271b.jpeg =500x

2.解题思路

 1. 将所有字符串映射到数字,使用unordered_map;
 2. 每个字符串都是一个集合,有ID;
 3. 根据每条关系,对ID进行合并;
 4. 对每个集合进行统计、加和,选择字典序最小的记录。

3.代码演示(C++)

class Solution 
{
    #define maxn 100010
    unordered_map <string, int> name2fre;
    unordered_map <string, int> name2ID;
    vector<string> ID2Name;
    string groupname[maxn];
    int groupfrq[maxn];
    int f[maxn];
    void init_set(int n) 
    {
        for(int i = 1; i <= n; ++i) 
        {
            f[i] = i;
        }
    }
    int find_set(int n) 
    {
        return (f[n]==n) ? n : (f[n] = find_set(f[n]));
    }
    int union_set(int a, int b) 
    {
        int fa = find_set(a);
        int fb = find_set(b);
        if(fa == fb) 
        {
            return 1;
        }
        f[fa] = fb;
        return 0;
    }
    string num2String(int num) 
    {
        if(!num) 
        {
            return "0";
        }
        string ret;
        while(num) 
        {
            ret.push_back(num % 10 + '0');
            num /= 10;
        }
        reverse(ret.begin(), ret.end());
        return ret;
    }
public:
    vector<string> trulyMostPopular(vector<string>& names, vector<string>& synonyms) 
    {
        int N = 0;
        ID2Name.push_back("");
        for(int i = 0; i < names.size(); ++i) 
        {
            int flag = 0;
            int fre = 0;
            string name;
            for(int j = 0; j < names[i].size(); ++j) 
            {
                if(names[i][j] == '(') 
                {
                    flag = 1;
                }
                else if(flag && names[i][j] != ')') 
                {
                    fre = fre * 10 + names[i][j] - '0';
                }
                else if(flag == 0) 
                {
                    name += names[i][j];
                }
            }
            name2fre[name] = fre;
            name2ID[name] = ++N;
            ID2Name.push_back(name);
        } 
        init_set(maxn - 1);
        for(int i = 0; i < synonyms.size(); ++i) 
        {
            int flag = 0;
            string first, second;
            for(int j = 0; j < synonyms[i].size(); ++j) 
            {
                if(synonyms[i][j] == '(' || synonyms[i][j] == ')') 
                {

                }
                else if(synonyms[i][j] == ',') 
                {
                    flag = 1;
                }
                else if(flag == 0) 
                {
                    first += synonyms[i][j];
                }
                else 
                {
                    second += synonyms[i][j];
                }
            }
            if(name2ID[first] == 0) 
            {
                name2fre[first] = 0;
                name2ID[first] = ++N;
                ID2Name.push_back(first);
            }
            if(name2ID[second] == 0) 
            {
                name2fre[second] = 0;
                name2ID[second] = ++N;
                ID2Name.push_back(second);
            }
            union_set( name2ID[first], name2ID[second] );
        }
        for(auto it = name2fre.begin(); it != name2fre.end(); it++) 
        {
            int ID = name2ID[it->first];
            int setID = find_set(ID);
            if (groupname[setID] == "" || it->first < groupname[setID]) 
            {
                groupname[setID] = it->first;
            }
            groupfrq[setID] += name2fre[it->first];
        }
        vector<string> ret;
        for(int i = 1; i <= N; ++i) 
        {
            if(groupfrq[i] == 0) 
            {
                continue;
            }
            string s = groupname[i] + "(" + num2String(groupfrq[i]) + ")";
            ret.push_back(s);
        }
        return ret;
    }
};

4.题目链接

题目传送门


总结

每月的最后几天是比较难熬,多看看基础的算法思路,题目多看题解,记录一下。
每天跟随英雄哥学习相关的算法,一个月会收获很多,如果你想了解更多关于知识星球的内容,欢迎联系我!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值