sorting a list and counting interchanges

Tim Peters tim.peters at gmail.com
Thu Apr 7 13:59:06 EDT 2005


[Paul Rubin]
> Writing a sorting function from scratch for this purpose seems like
> reinventing the wheel.

Yup!  list.sort() is going to be mounds faster.

> Tim's answer of simply counting the cycles (without having to pay
> attention to their length) is really clever.  I didn't realize you could do
> that.

It's a standard trick; see, e.g., Nijenhuis & Wilf's "Combinatorial
Algorithms" -- although it can be hard to extract the _sense_ out of
clever Fortran <0.7 wink>.

> Proving it is a cute exercise.  Hint: any cycle of odd length has an even
> number of swaps, and any cycle of even length has an odd number of swaps
> (another exercise).

More precisely, a cycle of length c can be written as the product of
c-1 transpositions.  If the permutation is the product of m disjoint
cycles of lengths c_1, c_2, ..., c_m, then decomposing those into
transpositions gives a total number of transpositions:

    (c_1-1) + (c_2-1) + ... + (c_m-1) =  [rearranging and combining the m 1's]
    (c_1 + c_2 + ... + c_m) - m = [each element appears exactly once in
                                                one cycle, since the
cycles are disjoint]
    number_of_elements - m

which the code spelled

    n - num_cycles

I think it's harder for some people to see why the

    assert j not in seen

must be true, although that's obvious after just a few hours' thought <wink>.



More information about the Python-list mailing list