Baby Names:政府每年都会公布一些最常见的婴儿名字和频率(同名婴儿的数量),其中的某些名字有多种拼法,根据婴儿名字、数量和同名表,统计每个名字实际婴儿数量。
这题的输入格式不友好,需要进行转换,具体为:
Names
为编号到名字到映射Name2Idx
为名字到编号的映射Synonyms
为编号形式的同名表
开始时,将每个名字都视为单独的集合,即Group
的下标和元素相同。然后扫描同名表Synonyms
,通过更新Group
中的元素实现集合的合并。
class Solution {
private:
vector<string> Names;
map<string, size_t> Name2Idx;
vector<int> Freqs;
vector<pair<size_t, size_t>> Synonyms;
vector<size_t> Group;
void addNameFreq(const string &name, const int freq)
{
Name2Idx[name] = Names.size();
Names.push_back(name);
Group.push_back(Group.size());
Freqs.push_back(freq);
}
void transformInput(const vector<string> &names, const vector<string> &synonyms)
{
for(string str : names)
{
string::size_type pos = str.find('(');
string name = str.substr(0, pos);
int freq = stoi(str.substr(pos + 1, str.size() - 2 - pos));
addNameFreq(name, freq);
}
for(string str : synonyms)
{
string::size_type pos = str.find(',');
string name1 = str.substr(1, pos - 1);
string name2 = str.substr(pos + 1, str.size() - 2 - pos);
if(Name2Idx.find(name1) == Name2Idx.end()){
addNameFreq(name1, 0);
}
if(Name2Idx.find(name2) == Name2Idx.end()){
addNameFreq(name1, 0);
}
Synonyms.push_back(make_pair(Name2Idx[name1], Name2Idx[name2]));
}
}
size_t findLeader(size_t i)
{
if(Group[i] == i) return i;
else return findLeader(Group[i]);
}
void groupName()
{
for(auto p : Synonyms)
{
size_t Leader1Idx = findLeader(p.first);
size_t Leader2Idx = findLeader(p.second);
if(Names[Leader1Idx] < Names[Leader2Idx]) Group[Leader2Idx] = Leader1Idx;
else Group[Leader1Idx] = Leader2Idx;
}
}
vector<string> transformOutput()
{
vector<string> result;
map<string, int> Popular;
for(size_t i = 0; i < Names.size(); i++)
{
size_t LeaderIdx = findLeader(i);
Popular[Names[LeaderIdx]] += Freqs[i];
}
for(auto iter = Popular.begin(); iter != Popular.end(); iter++)
{
result.push_back(iter->first);
result.back().push_back('(');
result.back().append(to_string(iter->second));
result.back().push_back(')');
}
return result;
}
public:
vector<string> trulyMostPopular(vector<string> &names, vector<string> &synonyms) {
transformInput(names, synonyms);
groupName();
return transformOutput();
}
};
除了并查集的方法,也可以通过划分连通子图求解,思路应该是没问题的,但是交上去后超时了。
class Solution {
private:
vector<string> Names;
map<string, size_t> Name2Idx;
vector<int> Freqs;
vector<vector<bool>> Graph;
map<string, int> Popular;
void addNameFreq(const string &name, const int freq)
{
Name2Idx[name] = Names.size();
Names.push_back(name);
Freqs.push_back(freq);
}
void transformInput(const vector<string> &names, const vector<string> &synonyms)
{
for(string str : names)
{
string::size_type pos = str.find('(');
string name = str.substr(0, pos);
int freq = stoi(str.substr(pos + 1, str.size() - 2 - pos));
addNameFreq(name, freq);
}
vector<pair<size_t, size_t>> Synonyms;
for(string str : synonyms)
{
string::size_type pos = str.find(',');
string name1 = str.substr(1, pos - 1);
string name2 = str.substr(pos + 1, str.size() - 2 - pos);
if(Name2Idx.find(name1) == Name2Idx.end()){
addNameFreq(name1, 0);
}
if(Name2Idx.find(name2) == Name2Idx.end()){
addNameFreq(name1, 0);
}
Synonyms.push_back(make_pair(Name2Idx[name1], Name2Idx[name2]));
}
Graph.assign(Names.size(), vector<bool>(Names.size(), false));
for(auto p : Synonyms)
{
Graph[p.first][p.second] = Graph[p.second][p.first] = true;
}
}
void groupName()
{
vector<bool> Visited(Names.size(), false);
for(size_t i = 0; i < Names.size(); i++)
{
if(!Visited[i]){
int TotalFreq = 0;
string LessName(Names[i]);
queue<size_t> group;
group.push(i);
Visited[i] = true;
while(!group.empty()){
size_t FrontIdx = group.front();
group.pop();
if(Names[FrontIdx] < LessName) LessName = Names[FrontIdx];
TotalFreq += Freqs[FrontIdx];
for(size_t adj = 0; adj < Names.size(); adj++)
{
if(Graph[FrontIdx][adj] && !Visited[adj]){
group.push(adj);
Visited[adj] = true;
}
}
}
Popular[LessName] = TotalFreq;
}
}
}
vector<string> transformOutput()
{
vector<string> result;
for(auto iter = Popular.begin(); iter != Popular.end(); iter++)
{
result.push_back(iter->first);
result.back().push_back('(');
result.back().append(to_string(iter->second));
result.back().push_back(')');
}
return result;
}
public:
vector<string> trulyMostPopular(vector<string> &names, vector<string> &synonyms) {
transformInput(names, synonyms);
groupName();
return transformOutput();
}
};