{
  "id": "sorting/counting-sort",
  "version": 1,
  "deterministic": true,
  "url": "/dsa/sorting/counting-sort",
  "topic": {
    "slug": "sorting",
    "title": "Sorting"
  },
  "title": "Counting Sort",
  "tagline": "Sorts without comparing anything — and that's how it beats n log n.",
  "vizKind": "bars",
  "complexity": {
    "time": {
      "best": "O(n + k)",
      "average": "O(n + k)",
      "worst": "O(n + k)"
    },
    "space": "O(k)",
    "growth": "linear",
    "note": "Linear in n + k, where k is the RANGE of values (not the count). That beats n log n — legitimately, because the n log n floor only binds comparison sorts. But the memory is k: a small range is wonderful, a huge range is catastrophic."
  },
  "code": {
    "javascript": "// No comparisons at all. It counts instead.\nfunction countingSort(a, maxValue) {\n  const count = new Array(maxValue + 1).fill(0);\n\n  // 1. How many of each value?\n  for (const v of a) count[v]++;\n\n  // 2. Read them back out, smallest first.\n  const out = [];\n  for (let v = 0; v <= maxValue; v++) {\n    for (let k = 0; k < count[v]; k++) out.push(v);\n  }\n\n  return out;\n}",
    "python": "# No comparisons at all. It counts instead.\ndef counting_sort(a, max_value):\n    count = [0] * (max_value + 1)\n\n    # 1. How many of each value?\n    for v in a: count[v] += 1\n\n    # 2. Read them back out, smallest first.\n    out = []\n    for v in range(max_value + 1):\n        for _ in range(count[v]): out.append(v)\n\n\n    return out\n",
    "java": "// No comparisons at all. It counts instead.\nint[] countingSort(int[] a, int maxValue) {\n  int[] count = new int[maxValue + 1];\n\n  // 1. How many of each value?\n  for (int v : a) count[v]++;\n\n  // 2. Read them back out, smallest first.\n  int[] out = new int[a.length];\n  int i = 0;\n  for (int v = 0; v <= maxValue; v++) {\n    for (int k = 0; k < count[v]; k++) out[i++] = v;\n  }\n  return out;\n}",
    "cpp": "// No comparisons at all. It counts instead.\nvector<int> countingSort(vector<int> a, int maxValue) {\n  vector<int> count(maxValue + 1, 0);\n\n  // 1. How many of each value?\n  for (int v : a) count[v]++;\n\n  // 2. Read them back out, smallest first.\n  vector<int> out;\n  for (int v = 0; v <= maxValue; v++) {\n    for (int k = 0; k < count[v]; k++) out.push_back(v);\n  }\n\n  return out;\n}"
  },
  "defaultInput": [
    4,
    2,
    7,
    1,
    4,
    2,
    6,
    4
  ],
  "defaultTarget": null,
  "inputHint": "Phase 1 tallies. Phase 2 reads the tallies back out. Zero comparisons.",
  "pitfalls": [
    {
      "wrong": "Using it when the range of values is huge.",
      "right": "The memory is the range, not the input size. Eight values spread across a billion needs a billion counters. Check the range before you reach for this."
    },
    {
      "wrong": "Believing it disproves the n log n lower bound.",
      "right": "It doesn't. That bound only applies to *comparison* sorts, and counting sort makes zero comparisons. It's not breaking the rule — the rule was never about it."
    },
    {
      "wrong": "Forgetting to handle negative numbers.",
      "right": "count[v] with a negative v is an out-of-bounds crash. Offset every value by the minimum first, or the very first negative number kills it."
    }
  ],
  "quiz": [
    {
      "q": "How does counting sort beat the n log n lower bound?",
      "options": [
        "It's cleverer than merge sort",
        "That bound only applies to comparison sorts, and counting sort makes zero comparisons",
        "It doesn't — it's actually n log n",
        "It uses more memory"
      ],
      "answer": 1,
      "why": "The theorem constrains sorts that work by comparing pairs. Counting sort tallies instead, so it was never bound by it. It sidesteps the wall rather than climbing it."
    },
    {
      "q": "What is 'k' in O(n + k)?",
      "options": [
        "The number of items",
        "The range of possible values",
        "The number of comparisons",
        "The number of buckets you feel like using"
      ],
      "answer": 1,
      "why": "k is the range — the span from the smallest possible value to the largest. That's how many counters you need, and it's the memory cost, regardless of how few items you're actually sorting."
    },
    {
      "q": "When is counting sort a terrible choice?",
      "options": [
        "When there are many duplicates",
        "When the values span a huge range, like arbitrary 32-bit integers",
        "When the list is already sorted",
        "When the list is short"
      ],
      "answer": 1,
      "why": "The memory is the range. Sorting a handful of numbers that happen to be billions apart would demand billions of counters. Small, known ranges only."
    }
  ],
  "problems": [
    {
      "name": "Sort Colors",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/sort-colors/"
    },
    {
      "name": "Height Checker",
      "difficulty": "Easy",
      "url": "https://leetcode.com/problems/height-checker/"
    },
    {
      "name": "Sort Array By Parity",
      "difficulty": "Easy",
      "url": "https://leetcode.com/problems/sort-array-by-parity/"
    }
  ],
  "trace": {
    "note": "Each frame is one immutable step: data snapshot, pointers, per-index roles, executing code line, and a one-sentence explanation.",
    "length": 18,
    "frames": [
      {
        "data": [
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c2-7",
            "value": 7
          },
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-6",
            "value": 6
          },
          {
            "id": "c7-4",
            "value": 4
          }
        ],
        "pointers": [],
        "highlights": [],
        "codeLine": 2,
        "variables": {
          "n": 8,
          "maxValue": 7
        },
        "explanation": "Counting sort never compares two values against each other. Not once. It just counts how many of each there are — and that's how it beats the n log n limit that binds every comparison sort.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "active"
      },
      {
        "data": [
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c2-7",
            "value": 7
          },
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-6",
            "value": 6
          },
          {
            "id": "c7-4",
            "value": 4
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 0
          }
        ],
        "highlights": [
          {
            "index": 0,
            "role": "compare"
          }
        ],
        "codeLine": 6,
        "variables": {
          "counting": 4,
          "count[4]": 1
        },
        "explanation": "Saw a 4. Bump its tally to 1. No comparison — just a tally mark.",
        "stats": {
          "comparisons": 1,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c2-7",
            "value": 7
          },
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-6",
            "value": 6
          },
          {
            "id": "c7-4",
            "value": 4
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 1
          }
        ],
        "highlights": [
          {
            "index": 1,
            "role": "compare"
          }
        ],
        "codeLine": 6,
        "variables": {
          "counting": 2,
          "count[2]": 1,
          "count[4]": 1
        },
        "explanation": "Saw a 2. Bump its tally to 1. No comparison — just a tally mark.",
        "stats": {
          "comparisons": 2,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c2-7",
            "value": 7
          },
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-6",
            "value": 6
          },
          {
            "id": "c7-4",
            "value": 4
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 2
          }
        ],
        "highlights": [
          {
            "index": 2,
            "role": "compare"
          }
        ],
        "codeLine": 6,
        "variables": {
          "counting": 7,
          "count[2]": 1,
          "count[4]": 1,
          "count[7]": 1
        },
        "explanation": "Saw a 7. Bump its tally to 1. No comparison — just a tally mark.",
        "stats": {
          "comparisons": 3,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c2-7",
            "value": 7
          },
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-6",
            "value": 6
          },
          {
            "id": "c7-4",
            "value": 4
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 3
          }
        ],
        "highlights": [
          {
            "index": 3,
            "role": "compare"
          }
        ],
        "codeLine": 6,
        "variables": {
          "counting": 1,
          "count[1]": 1,
          "count[2]": 1,
          "count[4]": 1,
          "count[7]": 1
        },
        "explanation": "Saw a 1. Bump its tally to 1. No comparison — just a tally mark.",
        "stats": {
          "comparisons": 4,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c2-7",
            "value": 7
          },
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-6",
            "value": 6
          },
          {
            "id": "c7-4",
            "value": 4
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 4
          }
        ],
        "highlights": [
          {
            "index": 4,
            "role": "compare"
          }
        ],
        "codeLine": 6,
        "variables": {
          "counting": 4,
          "count[1]": 1,
          "count[2]": 1,
          "count[4]": 2,
          "count[7]": 1
        },
        "explanation": "Saw a 4. Bump its tally to 2. No comparison — just a tally mark.",
        "stats": {
          "comparisons": 5,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c2-7",
            "value": 7
          },
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-6",
            "value": 6
          },
          {
            "id": "c7-4",
            "value": 4
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 5
          }
        ],
        "highlights": [
          {
            "index": 5,
            "role": "compare"
          }
        ],
        "codeLine": 6,
        "variables": {
          "counting": 2,
          "count[1]": 1,
          "count[2]": 2,
          "count[4]": 2,
          "count[7]": 1
        },
        "explanation": "Saw a 2. Bump its tally to 2. No comparison — just a tally mark.",
        "stats": {
          "comparisons": 6,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c2-7",
            "value": 7
          },
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-6",
            "value": 6
          },
          {
            "id": "c7-4",
            "value": 4
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 6
          }
        ],
        "highlights": [
          {
            "index": 6,
            "role": "compare"
          }
        ],
        "codeLine": 6,
        "variables": {
          "counting": 6,
          "count[1]": 1,
          "count[2]": 2,
          "count[4]": 2,
          "count[6]": 1,
          "count[7]": 1
        },
        "explanation": "Saw a 6. Bump its tally to 1. No comparison — just a tally mark.",
        "stats": {
          "comparisons": 7,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c2-7",
            "value": 7
          },
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-6",
            "value": 6
          },
          {
            "id": "c7-4",
            "value": 4
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 7
          }
        ],
        "highlights": [
          {
            "index": 7,
            "role": "compare"
          }
        ],
        "codeLine": 6,
        "variables": {
          "counting": 4,
          "count[1]": 1,
          "count[2]": 2,
          "count[4]": 3,
          "count[6]": 1,
          "count[7]": 1
        },
        "explanation": "Saw a 4. Bump its tally to 3. No comparison — just a tally mark.",
        "stats": {
          "comparisons": 8,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c2-7",
            "value": 7
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-6",
            "value": 6
          },
          {
            "id": "c7-4",
            "value": 4
          }
        ],
        "pointers": [],
        "highlights": [
          {
            "index": 0,
            "role": "swap"
          }
        ],
        "codeLine": 11,
        "variables": {
          "writing": 1,
          "placed": 1,
          "of": 8
        },
        "explanation": "count[1] said there is 1 — so write out a 1. Position 0 is settled.",
        "stats": {
          "comparisons": 8,
          "swaps": 1
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c2-7",
            "value": 7
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c6-6",
            "value": 6
          },
          {
            "id": "c7-4",
            "value": 4
          }
        ],
        "pointers": [],
        "highlights": [
          {
            "index": 0,
            "role": "sorted"
          },
          {
            "index": 1,
            "role": "swap"
          }
        ],
        "codeLine": 11,
        "variables": {
          "writing": 2,
          "placed": 2,
          "of": 8
        },
        "explanation": "count[2] said there are 2 — so write out a 2. Position 1 is settled.",
        "stats": {
          "comparisons": 8,
          "swaps": 2
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c2-7",
            "value": 7
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c6-6",
            "value": 6
          },
          {
            "id": "c7-4",
            "value": 4
          }
        ],
        "pointers": [],
        "highlights": [
          {
            "index": 0,
            "role": "sorted"
          },
          {
            "index": 1,
            "role": "sorted"
          },
          {
            "index": 2,
            "role": "swap"
          }
        ],
        "codeLine": 11,
        "variables": {
          "writing": 2,
          "placed": 3,
          "of": 8
        },
        "explanation": "count[2] said there are 2 — so write out a 2. Position 2 is settled.",
        "stats": {
          "comparisons": 8,
          "swaps": 3
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c2-7",
            "value": 7
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c6-6",
            "value": 6
          },
          {
            "id": "c7-4",
            "value": 4
          }
        ],
        "pointers": [],
        "highlights": [
          {
            "index": 0,
            "role": "sorted"
          },
          {
            "index": 1,
            "role": "sorted"
          },
          {
            "index": 2,
            "role": "sorted"
          },
          {
            "index": 3,
            "role": "swap"
          }
        ],
        "codeLine": 11,
        "variables": {
          "writing": 4,
          "placed": 4,
          "of": 8
        },
        "explanation": "count[4] said there are 3 — so write out a 4. Position 3 is settled.",
        "stats": {
          "comparisons": 8,
          "swaps": 4
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c2-7",
            "value": 7
          },
          {
            "id": "c6-6",
            "value": 6
          },
          {
            "id": "c7-4",
            "value": 4
          }
        ],
        "pointers": [],
        "highlights": [
          {
            "index": 0,
            "role": "sorted"
          },
          {
            "index": 1,
            "role": "sorted"
          },
          {
            "index": 2,
            "role": "sorted"
          },
          {
            "index": 3,
            "role": "sorted"
          },
          {
            "index": 4,
            "role": "swap"
          }
        ],
        "codeLine": 11,
        "variables": {
          "writing": 4,
          "placed": 5,
          "of": 8
        },
        "explanation": "count[4] said there are 3 — so write out a 4. Position 4 is settled.",
        "stats": {
          "comparisons": 8,
          "swaps": 5
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c7-4",
            "value": 4
          },
          {
            "id": "c2-7",
            "value": 7
          },
          {
            "id": "c6-6",
            "value": 6
          }
        ],
        "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": "swap"
          }
        ],
        "codeLine": 11,
        "variables": {
          "writing": 4,
          "placed": 6,
          "of": 8
        },
        "explanation": "count[4] said there are 3 — so write out a 4. Position 5 is settled.",
        "stats": {
          "comparisons": 8,
          "swaps": 6
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c7-4",
            "value": 4
          },
          {
            "id": "c6-6",
            "value": 6
          },
          {
            "id": "c2-7",
            "value": 7
          }
        ],
        "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": "swap"
          }
        ],
        "codeLine": 11,
        "variables": {
          "writing": 6,
          "placed": 7,
          "of": 8
        },
        "explanation": "count[6] said there is 1 — so write out a 6. Position 6 is settled.",
        "stats": {
          "comparisons": 8,
          "swaps": 7
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c7-4",
            "value": 4
          },
          {
            "id": "c6-6",
            "value": 6
          },
          {
            "id": "c2-7",
            "value": 7
          }
        ],
        "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"
          },
          {
            "index": 7,
            "role": "swap"
          }
        ],
        "codeLine": 11,
        "variables": {
          "writing": 7,
          "placed": 8,
          "of": 8
        },
        "explanation": "count[7] said there is 1 — so write out a 7. Position 7 is settled.",
        "stats": {
          "comparisons": 8,
          "swaps": 8
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "c3-1",
            "value": 1
          },
          {
            "id": "c1-2",
            "value": 2
          },
          {
            "id": "c5-2",
            "value": 2
          },
          {
            "id": "c0-4",
            "value": 4
          },
          {
            "id": "c4-4",
            "value": 4
          },
          {
            "id": "c7-4",
            "value": 4
          },
          {
            "id": "c6-6",
            "value": 6
          },
          {
            "id": "c2-7",
            "value": 7
          }
        ],
        "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"
          },
          {
            "index": 7,
            "role": "sorted"
          }
        ],
        "codeLine": 14,
        "variables": {
          "comparisons": 0,
          "n": 8,
          "maxValue": 7
        },
        "explanation": "Sorted — with exactly zero comparisons. O(n + k), where k is the range of values. But look at the catch: the memory is k, not n. Sort three numbers that are a billion apart and you'd need a billion counters.",
        "stats": {
          "comparisons": 8,
          "swaps": 8
        },
        "accent": "sorted"
      }
    ]
  }
}