Dec 3, LeetCode 451. Sort Characters By Frequency: Sometimes Python Is Magic

https://leetcode.com/problems/sort-characters-by-frequency/
Language: Python — Time: 2 minutes
Full Code on Gitfront.iohttps://github.com/cswartzell

I’ve been exploring development with Python for much of a year, and recently I feel like its really beginning to click. I’m falling in with the fanatics, Python is magic. Simple, powerful, readable, and intuitive. The standard and common libraries are amazing for just getting things done. Most of the times I wonder if there is an existing method for doing this or manipulating that, and after just a little googling… there just is, and not in some obscure package nobody has ever heard of, but often a core feature of standard types.

Case in point, todays Leetcode exercise (seemingly erroneously marked as a Medium difficulty), asks to simply return a string of characters, sorted by the frequency of the characters themselves. Built in sorting methods assume character sorting by alphabetic order.

Dead easy:
1. Create a frequency hashmap of the letters: This is the Python Counter() type
2. Sort this frequency map: Yep. As of Python 3.10 dicts, counters, sets etc (hashed types) now retain their ordering, so can indeed be sorted. Furthermore, Counter has a method that sorts by most common frequency already.
3. Iterate our Counter. We can use a list comprehension to recreate our string. By unpacking the Counter as a Tuple we get the character (key), and its frequency (value) in a single handy package we can simultaneously assign to two variables. Simultaneous assignment and automatic unpacking makes so much sense and eliminates a lot of clutter.
4. Generate the list of chars. In list comprehensions, the “*” operator means “repeat the previos value” as in [“X”*Y] would make a list “X” characters repeated Y times. This creates the list, in order, for the correct number of each character
5. Convert this back to a string. ****

**** Ok… here I sympathize with those that disparage Python. The “”.join(str) method seems… rather clunky. Why lead with the literal to be used as the separator and not treat it as an argument? It feels very odd, and doesn’t match almost any other syntax I know in the language. str.join(iterable, “seperator”) seems to make a lot more sense. Otherwise it feels like I’m operating on the object “”

Anyhow, all of this is simple, intuitive, and built in standard functions. This can elegantly be combined into a single line, and not a hacky “technically its one line” mess. It is completely logical, readable, efficient. As we are sorting the hashmap it is presumably O(n log n).

        return “”.join([x*y for (x, y) in Counter(s).most_common()])

Sometimes Python is magic. Relevant XKCD

Leave a comment