Ένα disjoint-set (union-find) παρακολουθεί στοιχεία χωρισμένα σε μη επικαλυπτόμενες ομάδες και απαντά και σε . Με και , και οι δύο πράξεις εκτελούνται σε — πρακτικά O(1) (α είναι η αντίστροφη συνάρτηση Ackermann).
Ένα disjoint-set (union-find) παρακολουθεί στοιχεία χωρισμένα σε μη επικαλυπτόμενες ομάδες και απαντά και σε . Με και , και οι δύο πράξεις εκτελούνται σε — πρακτικά O(1) (α είναι η αντίστροφη συνάρτηση Ackermann).
Κάθε σύνολο είναι ένα δέντρο; η ρίζα είναι ο αντιπρόσωπος του συνόλου. find περπατά προς τη ρίζα; union συνδέει μια ρίζα κάτω από μια άλλη.
find(x): follow parents to the root
union(a,b): attach the shorter tree under the taller (by rank)
path compression: after find, point nodes DIRECTLY at the root
before: a->b->c->root after: a->root, b->root, c->root
class DSU:
def __init__(self, n):
self.parent = list(range(n))
self.rank = [0]*n
def find(self, x): # path compression
while self.parent[x] != x:
self.parent[x] = self.parent[self.parent[x]] # halve path
x = self.parent[x]
return x
def union(self, a, b): # union by rank
ra, rb = self.find(a), self.find(b)
if ra == rb: return False
if self.rank[ra] < self.rank[rb]: ra, rb = rb, ra
self.parent[rb] = ra
if self.rank[ra] == self.rank[rb]: self.rank[ra] += 1
return True
| Πράξη | Χρόνος (με αμφότερες τις βελτιστοποιήσεις) |
|---|---|
| find | O(α(n)) ≈ O(1) |
| union | O(α(n)) ≈ O(1) |
Η Union-Find επιλύει προβλήματα ομαδοποίησης και συνδεσιμότητας που διαφορετικά θα απαιτούσαν επανειλημμένες O(n) διαδρομές γραφήματος, καταρρέοντάς τες σε σχεδόν O(1) ανά ερώτημα.
Είναι ένα βασικό εργαλείο κάθε φορά που πρέπει να συγχωνεύσετε σταδιακά σύνολα και να δοκιμάσετε τη συνδεσιμότητα — ένα συχνό θέμα συνέντευξης σε senior level.
Μια βιβλιοθήκη ερωτήσεων συνέντευξης IT με αναλυτικές απαντήσεις — από Junior έως Senior.
Δωρεά