題目描述:給一個整數數組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;
}