exercise: partition a list by equivalence

David Eppstein eppstein at ics.uci.edu
Fri Feb 18 21:39:44 EST 2005


In article <1108768870.455974.244590 at c13g2000cwb.googlegroups.com>,
 "John Machin" <sjmachin at lexicon.net> wrote:

> You don't need to think. This problem has been extensively picked over
> by folk who are a lot smarter than us, starting from 30 years ago.
> Google for "disjoint set" and "union-find". One gets the impression
> that the best possible algorithm would be slightly *worse* than O(n).

It can be solved by union-find
(e.g. with UnionFind from <http://www.ics.uci.edu/~eppstein/PADS/>):

import UnionFind
import sets

def merge(pairs):
    uf = UnionFind.UnionFind()
    items = sets.Set()
    for a,b in pairs:
        uf.union(a,b)
        items.add(a)
        items.add(b)
    leaders = {}
    for a in items:
        leaders.setdefault(uf[a],sets.Set()).add(a)
    return [list(component) for component in leaders.values()]

If you do all the unions before all the finds, as in this algorithm, 
union-find is O(n).

However it might be easier to treat the input pairs as the edges of a 
graph and apply a depth-first-search based graph connected components 
algorithm.

-- 
David Eppstein
Computer Science Dept., Univ. of California, Irvine
http://www.ics.uci.edu/~eppstein/



More information about the Python-list mailing list