《七月集训》第二十六天 并查集

Crazy_DM 2022-07-27 19:23:01

面试题17.07.婴儿名字

解题思路:

1.并查集就是通过某些关系把原本散乱的点放入同一个集合中,一个集合只有一个相同的父节点。这么看的话,新生婴儿的名字有的是可以放入同一个集合中的,因此这题我们使用并查集来解决。

2.我们将名字映射到一个数字中放在一个unorder_map,将名字对应的婴儿数量放入另一个u_m中。因为名字映射到数字中,我们可以用一个整型数组来代表并查集,数组元素放着该节点的父节点的ID

3.当我们进行完并查集的init,find, merge操作后统计有多少个连通分量,连通分量的总和是多少(不断累加),连通分量最小的字典序是谁(不断修改为集合中的最小字典序)

class Solution {
public:
    int fa[100010], groupSum[100010];
    string groupName[100010];
    unordered_map<string, int> name2Fre; //这个名字的数量
    unordered_map<string, int> name2Id;  //这个名字映射的Id 
    
    void init(int n) {
        for(int i = 1; i <= n; ++i) {
            fa[i] = i;
        }
    }
    int find(int x) {
        return (x == fa[x]) ? x : (fa[x] = find(fa[x]));
    }
    void merge(int i, int j) {
        int x = find(i), y = find(j);

        if(x == y) return;
        else {
            fa[x] = y;
        }
    } 

    string int2string(int i) {
        if(!i) return "0";
        string str = to_string(i);
        return str;
    }


    vector<string> trulyMostPopular(vector<string>& names, vector<string>& synonyms) {
        int idFrom0 = 0;
        for(int i = 0; i < names.size(); ++i) {
            int fre = 0, flag = 0;
            string name = "";
            for(int j = 0; j < names[i].size(); ++j) {
                if(names[i][j] == '(') {
                    flag = 1;
                    //continue;
                }
                else if(flag == 1 && names[i][j] != ')') {
                    fre *= 10;
                    fre += names[i][j] - '0';
                }
                else if(flag == 0){
                    name += names[i][j];
                }
            }

            name2Fre[name] = fre;
            name2Id[name] = ++idFrom0;
        }
        init(100010 - 1);

        for(int i = 0; i < synonyms.size(); ++i) {
            string name1, name2;
            int flag = 0;
            for(int j = 0; j < synonyms[i].size(); ++j) {
                if(synonyms[i][j] == ',') flag = 1;
                else if(flag && synonyms[i][j] != ')') name2 += synonyms[i][j];
                else if(!flag && synonyms[i][j] != '(') name1 +=synonyms[i][j];
            }

            if(name2Id[name1] == 0) {
                name2Fre[name1] = 0;
                name2Id[name1] = ++idFrom0;
            }
            if(name2Id[name2] == 0) {
                name2Fre[name2] = 0;
                name2Id[name2] = ++idFrom0;
            }
            merge(name2Id[name1], name2Id[name2]);
        }
        
        for(auto iter = name2Fre.begin(); iter != name2Fre.end(); ++iter) {
            int id = name2Id[iter -> first]; //名字
            int faId = find(id); //父节点编号
            if(groupName[faId] == "" || iter -> first < groupName[faId]) { //只有一个父节点,所以其他节点不会被更新
                groupName[faId] = iter -> first;
            }
            groupSum[faId] += name2Fre[iter -> first]; //数量
        }

        vector<string> ret;
        for(int i = 1; i <= idFrom0; ++i) {
            if(groupName[i] != "")
                ret.push_back(groupName[i] + "(" + int2string(groupSum[i]) + ")");
        }
        return ret;
    }
};

 

...全文
19 回复 打赏 收藏 举报
写回复
回复
切换为时间正序
请发表友善的回复…
发表回复
发帖
万人千题

6.2w+

社区成员

学习「 算法 」的捷径就是 「 题海战略 」,社区由「 夜深人静写算法 」作者创建,三年ACM经验,校集训队队长,亚洲区域赛金牌,世界总决赛选手。社区提供系统的训练,答疑解惑,面试经验,大厂内推等机会
社区管理员
  • 英雄哪里出来
  • Amy卜bo皮
  • Risso
加入社区
帖子事件
创建了帖子
2022-07-27 19:23
社区公告

QQ群:480072171

英雄算法交流 8 群