{
  "id": "sorting/radix-sort",
  "version": 1,
  "deterministic": true,
  "url": "/dsa/sorting/radix-sort",
  "topic": {
    "slug": "sorting",
    "title": "Sorting"
  },
  "title": "Radix Sort",
  "tagline": "Sort by the last digit first. It sounds backwards, and it's the only way it works.",
  "vizKind": "bars",
  "complexity": {
    "time": {
      "best": "O(d × n)",
      "average": "O(d × n)",
      "worst": "O(d × n)"
    },
    "space": "O(n + b)",
    "growth": "linear",
    "note": "d passes over n items, where d is the number of digits and b the base (10 here). On fixed-width keys d is a small constant, so this is effectively linear — genuinely faster than n log n. On values with wildly different lengths, d starts to hurt."
  },
  "code": {
    "javascript": "// Sort by the last digit. Then the next. Then the next.\nfunction radixSort(a) {\n  const maxValue = Math.max(...a);\n\n  for (let exp = 1; Math.floor(maxValue / exp) > 0; exp *= 10) {\n    a = countingSortByDigit(a, exp);\n  }\n  return a;\n}\n\nfunction countingSortByDigit(a, exp) {\n  const buckets = Array.from({ length: 10 }, () => []);\n\n  // Stability is everything: earlier items stay earlier.\n  for (const v of a) {\n    const digit = Math.floor(v / exp) % 10;\n    buckets[digit].push(v);\n  }\n\n  return buckets.flat();\n}",
    "python": "# Sort by the last digit. Then the next. Then the next.\ndef radix_sort(a):\n    max_value = max(a)\n    exp = 1\n\n    while max_value // exp > 0:\n        a = counting_sort_by_digit(a, exp)\n        exp *= 10\n\n    return a\n\n\ndef counting_sort_by_digit(a, exp):\n    buckets = [[] for _ in range(10)]\n\n    # Stability is everything: earlier items stay earlier.\n    for v in a:\n        digit = (v // exp) % 10\n        buckets[digit].append(v)\n\n    return [v for bucket in buckets for v in bucket]\n",
    "java": "// Sort by the last digit. Then the next. Then the next.\nint[] radixSort(int[] a) {\n  int maxValue = Arrays.stream(a).max().getAsInt();\n\n  for (int exp = 1; maxValue / exp > 0; exp *= 10) {\n    a = countingSortByDigit(a, exp);\n  }\n  return a;\n}\n\nint[] countingSortByDigit(int[] a, int exp) {\n  List<List<Integer>> buckets = new ArrayList<>();\n  for (int d = 0; d < 10; d++) buckets.add(new ArrayList<>());\n\n  // Stability is everything: earlier items stay earlier.\n  for (int v : a) {\n    int digit = (v / exp) % 10;\n    buckets.get(digit).add(v);\n  }\n\n  return flatten(buckets);\n}",
    "cpp": "// Sort by the last digit. Then the next. Then the next.\nvector<int> radixSort(vector<int> a) {\n  int maxValue = *max_element(a.begin(), a.end());\n\n  for (int exp = 1; maxValue / exp > 0; exp *= 10) {\n    a = countingSortByDigit(a, exp);\n  }\n  return a;\n}\n\nvector<int> countingSortByDigit(vector<int>& a, int exp) {\n  vector<vector<int>> buckets(10);\n\n  // Stability is everything: earlier items stay earlier.\n  for (int v : a) {\n    int digit = (v / exp) % 10;\n    buckets[digit].push_back(v);\n  }\n\n  vector<int> out;\n  for (auto& b : buckets) for (int v : b) out.push_back(v);\n  return out;\n}"
  },
  "defaultInput": [
    170,
    45,
    75,
    90,
    24,
    2,
    66
  ],
  "defaultTarget": null,
  "inputHint": "Units digit first, then tens, then hundreds. Each pass must be stable.",
  "pitfalls": [
    {
      "wrong": "Sorting from the most significant digit first.",
      "right": "Each pass would destroy the last one's work. Least-significant-first, combined with stability, is what makes the passes accumulate instead of fight."
    },
    {
      "wrong": "Using an unstable sort for each digit pass.",
      "right": "Stability is not a nice-to-have here — it's the load-bearing wall. Break it and the algorithm is simply wrong."
    },
    {
      "wrong": "Forgetting negative numbers.",
      "right": "Digits don't have signs. Split into negatives and positives, sort separately, and reverse the negatives — or the minus signs will be silently ignored."
    }
  ],
  "quiz": [
    {
      "q": "Why does radix sort start with the LAST digit?",
      "options": [
        "It's arbitrary — either end works",
        "Because each stable pass preserves the previous pass's work, so the ordering accumulates",
        "Because the last digit is most important",
        "To save memory"
      ],
      "answer": 1,
      "why": "Least-significant-first plus stability means numbers that tie on the current digit keep the order the previous pass gave them. Every pass builds on the last instead of destroying it."
    },
    {
      "q": "What breaks radix sort completely?",
      "options": [
        "Duplicate values",
        "Using an unstable sort for each digit pass",
        "A large number of items",
        "Already-sorted input"
      ],
      "answer": 1,
      "why": "Stability is load-bearing. If a pass reorders numbers that tie on the current digit, it wipes out everything the earlier passes established, and the result is just wrong."
    },
    {
      "q": "What's radix sort's complexity, and when does it beat n log n?",
      "options": [
        "O(n²), never",
        "O(d × n) — it beats n log n when d (the number of digits) is a small constant",
        "O(n log n), the same as merge sort",
        "O(log n), always"
      ],
      "answer": 1,
      "why": "d passes over n items. On fixed-width keys like IDs or dates, d is a small constant, making it effectively linear and genuinely faster than any comparison sort."
    }
  ],
  "problems": [
    {
      "name": "Sort an Array",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/sort-an-array/"
    },
    {
      "name": "Maximum Gap",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/maximum-gap/"
    },
    {
      "name": "Sort Colors",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/sort-colors/"
    }
  ],
  "trace": {
    "note": "Each frame is one immutable step: data snapshot, pointers, per-index roles, executing code line, and a one-sentence explanation.",
    "length": 29,
    "frames": [
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [],
        "highlights": [],
        "codeLine": 2,
        "variables": {
          "n": 7,
          "maxValue": 170
        },
        "explanation": "Radix sort never compares whole numbers either. It sorts by one digit at a time — starting with the LAST digit, which sounds backwards and is exactly the trick.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "active"
      },
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [],
        "highlights": [],
        "codeLine": 5,
        "variables": {
          "pass": "units",
          "exp": 1
        },
        "explanation": "Pass over the units digit. Drop each number into the bucket for its units digit, keeping ties in their current order.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "pivot"
      },
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 0
          }
        ],
        "highlights": [
          {
            "index": 0,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 170,
          "digit": 0,
          "bucket": 0
        },
        "explanation": "170 — its units digit is 0, so it goes into bucket 0.",
        "stats": {
          "comparisons": 1,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 1
          }
        ],
        "highlights": [
          {
            "index": 1,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 45,
          "digit": 5,
          "bucket": 5
        },
        "explanation": "45 — its units digit is 5, so it goes into bucket 5.",
        "stats": {
          "comparisons": 2,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 2
          }
        ],
        "highlights": [
          {
            "index": 2,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 75,
          "digit": 5,
          "bucket": 5
        },
        "explanation": "75 — its units digit is 5, so it goes into bucket 5.",
        "stats": {
          "comparisons": 3,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 3
          }
        ],
        "highlights": [
          {
            "index": 3,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 90,
          "digit": 0,
          "bucket": 0
        },
        "explanation": "90 — its units digit is 0, so it goes into bucket 0.",
        "stats": {
          "comparisons": 4,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 4
          }
        ],
        "highlights": [
          {
            "index": 4,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 24,
          "digit": 4,
          "bucket": 4
        },
        "explanation": "24 — its units digit is 4, so it goes into bucket 4.",
        "stats": {
          "comparisons": 5,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 5
          }
        ],
        "highlights": [
          {
            "index": 5,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 2,
          "digit": 2,
          "bucket": 2
        },
        "explanation": "2 — its units digit is 2, so it goes into bucket 2.",
        "stats": {
          "comparisons": 6,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 6
          }
        ],
        "highlights": [
          {
            "index": 6,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 66,
          "digit": 6,
          "bucket": 6
        },
        "explanation": "66 — its units digit is 6, so it goes into bucket 6.",
        "stats": {
          "comparisons": 7,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [],
        "highlights": [],
        "codeLine": 21,
        "variables": {
          "pass": "units",
          "order": "170 90 2 24 45 75 66"
        },
        "explanation": "Tip the buckets out, 0 through 9. The list is now sorted by its units digit — and, crucially, numbers that tied on this digit are still in the order the last pass left them. That stability is what stops this pass from wrecking the previous one.",
        "stats": {
          "comparisons": 7,
          "swaps": 1
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [],
        "highlights": [],
        "codeLine": 5,
        "variables": {
          "pass": "tens",
          "exp": 10
        },
        "explanation": "Pass over the tens digit. Drop each number into the bucket for its tens digit, keeping ties in their current order.",
        "stats": {
          "comparisons": 7,
          "swaps": 1
        },
        "accent": "pivot"
      },
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 0
          }
        ],
        "highlights": [
          {
            "index": 0,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 170,
          "digit": 7,
          "bucket": 7
        },
        "explanation": "170 — its tens digit is 7, so it goes into bucket 7.",
        "stats": {
          "comparisons": 8,
          "swaps": 1
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 1
          }
        ],
        "highlights": [
          {
            "index": 1,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 90,
          "digit": 9,
          "bucket": 9
        },
        "explanation": "90 — its tens digit is 9, so it goes into bucket 9.",
        "stats": {
          "comparisons": 9,
          "swaps": 1
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 2
          }
        ],
        "highlights": [
          {
            "index": 2,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 2,
          "digit": 0,
          "bucket": 0
        },
        "explanation": "2 — its tens digit is 0, so it goes into bucket 0.",
        "stats": {
          "comparisons": 10,
          "swaps": 1
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 3
          }
        ],
        "highlights": [
          {
            "index": 3,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 24,
          "digit": 2,
          "bucket": 2
        },
        "explanation": "24 — its tens digit is 2, so it goes into bucket 2.",
        "stats": {
          "comparisons": 11,
          "swaps": 1
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 4
          }
        ],
        "highlights": [
          {
            "index": 4,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 45,
          "digit": 4,
          "bucket": 4
        },
        "explanation": "45 — its tens digit is 4, so it goes into bucket 4.",
        "stats": {
          "comparisons": 12,
          "swaps": 1
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 5
          }
        ],
        "highlights": [
          {
            "index": 5,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 75,
          "digit": 7,
          "bucket": 7
        },
        "explanation": "75 — its tens digit is 7, so it goes into bucket 7.",
        "stats": {
          "comparisons": 13,
          "swaps": 1
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c6-66",
            "value": 66
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 6
          }
        ],
        "highlights": [
          {
            "index": 6,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 66,
          "digit": 6,
          "bucket": 6
        },
        "explanation": "66 — its tens digit is 6, so it goes into bucket 6.",
        "stats": {
          "comparisons": 14,
          "swaps": 1
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c6-66",
            "value": 66
          },
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          }
        ],
        "pointers": [],
        "highlights": [],
        "codeLine": 21,
        "variables": {
          "pass": "tens",
          "order": "2 24 45 66 170 75 90"
        },
        "explanation": "Tip the buckets out, 0 through 9. The list is now sorted by its tens digit — and, crucially, numbers that tied on this digit are still in the order the last pass left them. That stability is what stops this pass from wrecking the previous one.",
        "stats": {
          "comparisons": 14,
          "swaps": 2
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c6-66",
            "value": 66
          },
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          }
        ],
        "pointers": [],
        "highlights": [],
        "codeLine": 5,
        "variables": {
          "pass": "hundreds",
          "exp": 100
        },
        "explanation": "Pass over the hundreds digit. Drop each number into the bucket for its hundreds digit, keeping ties in their current order.",
        "stats": {
          "comparisons": 14,
          "swaps": 2
        },
        "accent": "pivot"
      },
      {
        "data": [
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c6-66",
            "value": 66
          },
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 0
          }
        ],
        "highlights": [
          {
            "index": 0,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 2,
          "digit": 0,
          "bucket": 0
        },
        "explanation": "2 — its hundreds digit is 0, so it goes into bucket 0.",
        "stats": {
          "comparisons": 15,
          "swaps": 2
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c6-66",
            "value": 66
          },
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 1
          }
        ],
        "highlights": [
          {
            "index": 1,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 24,
          "digit": 0,
          "bucket": 0
        },
        "explanation": "24 — its hundreds digit is 0, so it goes into bucket 0.",
        "stats": {
          "comparisons": 16,
          "swaps": 2
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c6-66",
            "value": 66
          },
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 2
          }
        ],
        "highlights": [
          {
            "index": 2,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 45,
          "digit": 0,
          "bucket": 0
        },
        "explanation": "45 — its hundreds digit is 0, so it goes into bucket 0.",
        "stats": {
          "comparisons": 17,
          "swaps": 2
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c6-66",
            "value": 66
          },
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 3
          }
        ],
        "highlights": [
          {
            "index": 3,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 66,
          "digit": 0,
          "bucket": 0
        },
        "explanation": "66 — its hundreds digit is 0, so it goes into bucket 0.",
        "stats": {
          "comparisons": 18,
          "swaps": 2
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c6-66",
            "value": 66
          },
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 4
          }
        ],
        "highlights": [
          {
            "index": 4,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 170,
          "digit": 1,
          "bucket": 1
        },
        "explanation": "170 — its hundreds digit is 1, so it goes into bucket 1.",
        "stats": {
          "comparisons": 19,
          "swaps": 2
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c6-66",
            "value": 66
          },
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 5
          }
        ],
        "highlights": [
          {
            "index": 5,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 75,
          "digit": 0,
          "bucket": 0
        },
        "explanation": "75 — its hundreds digit is 0, so it goes into bucket 0.",
        "stats": {
          "comparisons": 20,
          "swaps": 2
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c6-66",
            "value": 66
          },
          {
            "id": "c0-170",
            "value": 170
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 6
          }
        ],
        "highlights": [
          {
            "index": 6,
            "role": "compare"
          }
        ],
        "codeLine": 18,
        "variables": {
          "value": 90,
          "digit": 0,
          "bucket": 0
        },
        "explanation": "90 — its hundreds digit is 0, so it goes into bucket 0.",
        "stats": {
          "comparisons": 21,
          "swaps": 2
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c6-66",
            "value": 66
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c0-170",
            "value": 170
          }
        ],
        "pointers": [],
        "highlights": [],
        "codeLine": 21,
        "variables": {
          "pass": "hundreds",
          "order": "2 24 45 66 75 90 170"
        },
        "explanation": "Tip the buckets out, 0 through 9. The list is now sorted by its hundreds digit — and, crucially, numbers that tied on this digit are still in the order the last pass left them. That stability is what stops this pass from wrecking the previous one.",
        "stats": {
          "comparisons": 21,
          "swaps": 3
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c1-45",
            "value": 45
          },
          {
            "id": "c6-66",
            "value": 66
          },
          {
            "id": "c2-75",
            "value": 75
          },
          {
            "id": "c3-90",
            "value": 90
          },
          {
            "id": "c0-170",
            "value": 170
          }
        ],
        "pointers": [],
        "highlights": [
          {
            "index": 0,
            "role": "sorted"
          },
          {
            "index": 1,
            "role": "sorted"
          },
          {
            "index": 2,
            "role": "sorted"
          },
          {
            "index": 3,
            "role": "sorted"
          },
          {
            "index": 4,
            "role": "sorted"
          },
          {
            "index": 5,
            "role": "sorted"
          },
          {
            "index": 6,
            "role": "sorted"
          }
        ],
        "codeLine": 8,
        "variables": {
          "passes": 3,
          "comparisons": 0
        },
        "explanation": "Sorted, in 3 passes and zero comparisons. Radix sort is O(d × n) where d is the number of digits — so on a big pile of fixed-width keys it genuinely beats n log n. Try it on numbers of wildly different lengths and the d starts to hurt.",
        "stats": {
          "comparisons": 21,
          "swaps": 3
        },
        "accent": "sorted"
      }
    ]
  }
}