[LeetCode][C++]面试题 17.07. 婴儿名字/并查集

面试题 17.07. 婴儿名字
每年,政府都会公布一万个最常见的婴儿名字和它们出现的频率,也就是同名婴儿的数量。有些名字有多种拼法,例如,John 和 Jon 本质上是相同的名字,但被当成了两个名字公布出来。给定两个列表,一个是名字及对应的频率,另一个是本质相同的名字对。设计一个算法打印出每个真实名字的实际频率。注意,如果 John 和 Jon 是相同的,并且 Jon 和 Johnny 相同,则 John 与 Johnny 也相同,即它们有传递和对称性。

在结果列表中,选择字典序最小的名字作为真实名字。

示例:
输入:names = [“John(15)”,“Jon(12)”,“Chris(13)”,“Kris(4)”,“Christopher(19)”], synonyms = ["(Jon,John)","(John,Johnny)","(Chris,Kris)","(Chris,Christopher)"]
输出:[“John(27)”,“Chris(36)”]

提示:
names.length <= 100000


代码:

class Solution {
public:

    unordered_map<string,int> name_freq;
    unordered_map<string,string> pre;

    string find(string root)
    {
        string son,tmp;
        son=root;
        while(root!=pre[root])  //找到父节点
            root=pre[root];
        while(son!=root)  //路径压缩
        {
            tmp=pre[son];
            pre[son]=root;
            son=tmp;
        }
        return root;
    }

    void join(string r1, string r2)
    {
        if(pre.find(r1)==pre.end() || pre.find(r2)==pre.end())
            return;
        string p1=find(r1);
        string p2=find(r2);
        if(p1!=p2)
        {            
            if(p1<p2)
            {
                pre[p2]=p1;
                int tmp_freq=name_freq[p2];
                name_freq.erase(p2);
                name_freq[p1]+=tmp_freq;
            }else{
                pre[p1]=p2;
                int tmp_freq=name_freq[p1];
                name_freq.erase(p1);
                name_freq[p2]+=tmp_freq;
            }           
        }
    }

    vector<string> trulyMostPopular(vector<string>& names, vector<string>& synonyms)
    {
	    for (auto c : names)
	    {
		    int ind = c.find('(');
		    string tmp_name = c.substr(0, ind);
		    int tmp_freq = stoi(c.substr(ind + 1, c.length() - ind - 2));
		    name_freq[tmp_name] = tmp_freq;
		    pre[tmp_name] = tmp_name;
	    }
	    for (auto c : synonyms)
	    {
		    int ind = c.find(',');
		    string tmp_name1 = c.substr(1, ind - 1);
		    string tmp_name2 = c.substr(ind + 1, c.length() - ind - 2);
		    join(tmp_name1, tmp_name2);
	    }
	    vector<string> res;
	    for (auto it = name_freq.begin(); it != name_freq.end(); it++)
	    {
		    string tmp_res = it->first + "(" + to_string(it->second) + ")";
		    res.push_back(tmp_res);
	    }
	    return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值