思路过程:
看到题目的一瞬间觉得so easy,因为类似题目做到过好几次,leetcode上很多求最大连通子图大小之类的题目都可以用并查集来解决。(后来被妥妥打脸,花了一小时才搞定,555)
版本1:
class Solution {
public:
unordered_map<int,int> P;
unordered_map<int,int> count;
int findfather(int x){
if(P.find(x) == P.end())
{
P[x] = x;
count[x] = 1;
}
if(P[x] != x)
P[x] = findfather(P[x]);
return P[x];
}
void togather(int x,int y){
int px = findfather(x);
int py = findfather(y);
if(px<py){
count[px] += count[py];
P[py] = px;
}
else if(px>py){
count[py] += count[px];
P[px] = py;
}
}
void count_number(int x,set<int> &temp){
//分解质因数
int n =2;
while(n<=x){
while(x%n == 0){
x = x/n;
temp.insert(n);
}
n+=1;
}
}
int largestComponentSize(vector<int>& A) {
unordered_map<int,int> factormap;
for(auto a :A){
set<int> temp;
count_number(a,temp);
int x = a,y = a;
for(auto b : temp){
if(factormap.find(b) != factormap.end()){
y = factormap[b];
togather(x,y);
}else
factormap[b] = a;
}
}
int maxcount = 0;
for(unordered_map<int,int>::iterator it = count.begin();it!=count.end();it++)
maxcount = max(maxcount,(*it).second);
return maxcount;
}
};
提交后,果不其然的Boom 爆炸了。查找可以优化的地方:1.最后的循环查找最大count是可以在每次togather中完成;2.分解质因数的过程和归并过程可以放在一起;3.可以开一个set来存放所有可能的质数。
第一次修改后的代码:
class Solution {
public:
unordered_map<int,int> P;
unordered_map<int,int> count;
int maxcount = 0;
int findfather(int x){
if(P.find(x) == P.end())
{
P[x] = x;
count[x] = 1;
}
if(P[x] != x)
P[x] = findfather(P[x]);
return P[x];
}
void togather(int x,int y){
int px = findfather(x);
int py = findfather(y);
if(px!=py){
count[py] += count[px];
P[px] = py;
maxcount = max(maxcount,count[py]);
}
}
int largestComponentSize(vector<int>& A) {
unordered_map<int,int> factormap;
vector<int> prime(100001,1);
set<int> isp;//存放质数
for(int i =2;i<100001;i++)
{
if(prime[i] != 0)
isp.insert(i);
for(int j = 2;j*i<100001;j++)
prime[i*j] = 0;
}
for(auto a :A){
for(set<int>::iterator it = isp.begin();(it!=isp.end())&& ((*it)<= a);it++)
{
if(a % (*it) == 0)
{
if(factormap.find((*it)) != factormap.end())
togather(a,factormap[(*it)]);
else
factormap[(*it)] = a;
}
}
}
return maxcount;
}
};
还是Time Limit Exceeded.emmmm,换一种判断分解质因数过程结束的方法
修改后的代码:
class Solution {
public:
unordered_map<int,int> P;
unordered_map<int,int> count;
int maxcount = 0;
int findfather(int x){
if(P.find(x) == P.end())
{
P[x] = x;
count[x] = 1;
}
if(P[x] != x)
P[x] = findfather(P[x]);
return P[x];
}
void togather(int x,int y){
int px = findfather(x);
int py = findfather(y);
if(px!=py){
count[py] += count[px];
P[px] = py;
maxcount = max(maxcount,count[py]);
}
}
int largestComponentSize(vector<int>& A) {
unordered_map<int,int> factormap;
vector<int> prime(100001,1);
set<int> isp;
for(int i =2;i<100001;i++)
{
if(prime[i] != -1)
isp.insert(i);
for(int j = 1;j*i<100001;j++)
prime[i*j] = -1;
}
for(auto a :A){
int y = a;
for(set<int>::iterator it = isp.begin();(it!=isp.end())&& y>1;it++)
{
int x = *it;
if(y % x == 0)
{
if(factormap.find(x) != factormap.end())
togather(a,factormap[x]);
else
{
factormap[x] = a;
}
while(y%x == 0)
y /= x;
}
}
}
return maxcount;
}
};
emmm,依旧爆炸,实在想不出,然后看了大佬对于分解质因数过程的优化
代码:
class Solution {
public:
unordered_map<int,int> P;
unordered_map<int,int> count;
int maxcount = 0;
int findfather(int x){
if(P.find(x) == P.end())
{
P[x] = x;
count[x] = 1;
}
if(P[x] != x)
P[x] = findfather(P[x]);
return P[x];
}
void togather(int x,int y){
int px = findfather(x);
int py = findfather(y);
if(px!=py){
count[py] += count[px];
P[px] = py;
maxcount = max(maxcount,count[py]);
}
}
int largestComponentSize(vector<int>& A) {
unordered_map<int,int> factormap;
vector<int> prime(100001,1);
set<int> isp;
for(int i =2;i<100001;i++)
{
if(prime[i] != -1)
isp.insert(i);
for(int j = 1;j*i<100001;j++)
prime[i*j] = -1;
}
for(auto a :A){
int y = a;
for(set<int>::iterator it = isp.begin();(it!=isp.end())&& y>1;it++)
{
int x = isp.find(y)==isp.end()?*it:y;//主要改了这里,减少循环次数
if(y % x == 0)
{
if(factormap.find(x) != factormap.end())
togather(a,factormap[x]);
else
{
factormap[x] = a;
}
while(y%x == 0)
y /= x;
}
}
}
return maxcount;
}
};
通过啦,runtime 480 ms
——————————————
然后发现prime似乎可以用来代替factormap
修改后的代码:
class Solution {
public:
unordered_map<int,int> P;
unordered_map<int,int> count;
int maxcount = 0;
int findfather(int x){
if(P.find(x) == P.end())
{
P[x] = x;
count[x] = 1;
}
if(P[x] != x)
P[x] = findfather(P[x]);
return P[x];
}
void togather(int x,int y){
int px = findfather(x);
int py = findfather(y);
if(px!=py){
count[py] += count[px];
P[px] = py;
maxcount = max(maxcount,count[py]);
}
}
int largestComponentSize(vector<int>& A) {
vector<int> prime(100001,1);
set<int> isp;
for(int i =2;i<100001;i++)
{
if(prime[i] != -1)
isp.insert(i);
for(int j = 1;j*i<100001;j++)
prime[i*j] = -1;
}
for(auto a :A){
int y = a;
for(set<int>::iterator it = isp.begin();(it!=isp.end())&& y>1;it++)
{
int x = isp.find(y)==isp.end()?*it:y;
if(y % x == 0)
{
if(prime[x]!= -1)
togather(a,prime[x]);
else
{
prime[x] = a;
}
while(y%x == 0)
y /= x;
}
}
}
return maxcount;
}
};
runtime 452 ms