题目描述:给一个整数数组a[], 找到其中包含最多连续数的子集,比如给:15, 7, 12, 6, 14, 13, 9, 11,则返回: 5:[11, 12, 13, 14, 15]
思路:初始化每个树子集一个集合,预处理每个数的数值哈希到一张表中,内容存下标,扫一次数组,每次取找val+1以及val-1的数,如果找到了把两者的集合合并,合并时可以按子集的大小进行启发式合并,即小的集合合并到多的集合中,这样能够尽量使并查集的所有子节点都接近根位置,加快查询效率。
Code:
int find(int x) {
if(x == fa[x]) return x;
return fa[x] = find(fa[x]);
}
void join(int x, int y) { //合并
int px = find(x);
int py = find(y);
if(px == py) return ;
if(rank[px]>rank[py]) {
fa[py] = px;
rank[px] += rank[py];
} else {
fa[px] = py;
rank[py] += rank[px];
}
}
void solve() {
memset(rank, 0, sizeof(rank));
memset(fa, 0, sizeof(fa));
unordered_map<int, int> hash;
hash.clear();
for(int i=1; i<=n; i++) {
rank[i]=1;
fa[i]=i;
hash[val[i]]=i; //键唯一,附带去重
} //预处理
for(int i=1; i<=n; i++) {
int cur = val[i];
if(hash.find(cur-1) != hash.end()) join(i, hash[cur-1]);
if(hash.find(cur+1) != hash.end()) join(i, hash[cur+1]);
}
int maxSize = rank[1], maxIndex = 1;
for(int i=2; i<=n; i++) {
if(rank[i] > maxSize)
maxSize=rank[i], maxIndex=i; //记录最大的那个团根
}
cout << maxSize << endl;
for(int i=1; i<= n; i++)
if(rank[i] == maxSize && hash[val[i]] == i)
cout << val[i] << ' ';
cout << endl;
}