Skip to content
AI360Xpert
Beta
GeeksforGeeks: HardGreedy

Huffman Coding

Official exercise: GeeksforGeeks

Problem in Plain English

Build a Huffman prefix-code tree from distinct symbols and their frequencies. Return leaf codes in preorder, using original symbol positions to resolve equal frequencies.

Problem Statement

This page solves GeeksforGeeks Huffman Encoding. Given distinct symbols s and corresponding frequencies f, repeatedly combine the two nodes of least frequency into a parent whose frequency is their sum. The smaller node goes left. For equal frequencies, the subtree containing the earliest symbol in the original string goes left. Return the leaf codes in left-before-right preorder, assigning 0 to a left edge and 1 to a right edge. The output is in tree order, not in the order of s.

The statement does not state a frequency magnitude bound. Its linked official article resolves the singleton convention as code 0. Here frequencies are nonnegative integer counts; merged weights use exact arithmetic. With one symbol the root is already a leaf: emit 0 rather than the mathematical empty path, following that official article. The published GFG Java wrapper accepts int frequencies; the JavaScript method additionally accepts BigInt or decimal strings for exact larger counts.

Constraints

  • 1 <= s.length = f.length <= 26; symbols are distinct.
  • The official statement gives no numeric frequency bound; do not infer one from the examples.
  • These solutions assume nonnegative integer frequencies and preserve their exact sums. Java uses the official int[] signature and BigInteger internally.

Examples

Example 1

Input
s = "abcdef", f = [5,9,12,13,16,45]
Output
["0","100","101","1100","1101","111"]

Preorder leaves are f,c,d,a,b,e. The weighted path length is 45 + 24 + 26 + 20 + 36 + 48 = 199.

Example 2

Input
s = "x", f = [7]
Output
["0"]

The singleton root has no edges, but the linked official article assigns code 0 so the symbol has a nonempty code.

Example 3

Input
s = "abcd", f = [1,1,2,2]
Output
["0","100","101","11"]

Merge a and b to weight 2 with earliest index 0. It precedes c at index 2 among weight-2 nodes; merging that parent with c gives weight 4. Then d (2) goes left of that parent (4). Preorder is d,a,b,c with codes 0,100,101,11.

Example 4

Input
s = "abcd", f = [1,1,1,1]
Output
["00","01","10","11"]

Pairs (a,b) and (c,d) each weigh 2. The subtree containing a goes left of the subtree containing c, yielding codes in symbol order.

Intuition

A prefix code gives each symbol a root-to-leaf bit path; no leaf path can be the prefix of another leaf path. Frequent symbols should have shorter paths because each extra edge costs that symbol one bit per occurrence. The least frequent pair can be deepest siblings, so merge them into one temporary symbol and repeat. In Example 1 the 5 and 9 leaves merge to 14, while the 45 leaf eventually becomes the root’s left child with code 0. Keep the actual child pointers: the sum of merge costs measures compression cost but cannot produce the codes.

Approaches

Huffman Tree

Optimal

Solution Details

Reveal Huffman Tree: intuition, complexity, and code

Hints

Hint 1
A code is a leaf path, so keep both children when you combine nodes.
Hint 2
Which two frequencies can occupy deepest sibling leaves without increasing the cost?
Hint 3
Merge the two minima using earliest original index for ties, then emit left-0 and right-1 paths in preorder.

Edge Cases

  • A singleton returns ["0"] under the linked official article’s convention; it does not return an empty list or an empty code.
  • Equal internal and leaf weights must compare earliest subtree indices, not creation order.
  • Zero counts still receive leaf codes; they do not invalidate the exchange argument.
  • Merged sums can overflow a fixed-width type even when each input frequency fits it.

Common Mistakes and Interview Tips

  • Returning only the sum of merged weights never constructs the requested codes.
  • Returning codes in s order differs from the source’s preorder output.
  • Using heap insertion order for ties can disagree with original-symbol subtree order.
  • Converting a rounded JavaScript Number to BigInt cannot restore the original frequency; supply exact input.

Key Takeaway

A greedy contraction needs an exchange argument and a way to expand the contracted solution. Retain structure, define ties for internal objects, and include the cost of producing the requested output.