Character Frequency Counting

Learn Character Frequency Counting with practical examples, explanations, best practices, and real-world coding techniques.

What Is Character Frequency?

Character frequency means counting how many times each character appears in a string. It is a common string-processing problem and an important example of using a hash map or frequency table to organize information efficiently.

For example, consider the string "banana". The character b appears once, a appears three times, and n appears twice.

Input:  "banana"

Frequency:
b → 1
a → 3
n → 2

Why Character Frequency Matters

Character-frequency counting appears in many programming problems. Instead of repeatedly searching the entire string for every character, we can process the string once and store the count for each character.

  • Finding duplicate characters
  • Checking whether two strings are anagrams
  • Finding the first non-repeating character
  • Building frequency tables
  • Counting characters for text-processing applications
  • Solving coding interview problems

Using an Object as a Frequency Map

In JavaScript, a plain object can be used as a simple frequency map. Each character becomes a property, and its value represents the number of times that character has appeared.

const text = "banana";
const frequency = {};

for (const char of text) {
  frequency[char] = (frequency[char] || 0) + 1;
}

console.log(frequency);
// { b: 1, a: 3, n: 2 }

The expression (frequency[char] || 0) + 1 handles both cases: a character that has already been counted and a character appearing for the first time.

How the Counting Process Works

Consider the string "hello". We process each character from left to right.

Character Frequency Before Frequency After
h 0 h → 1
e 0 e → 1
l 0 l → 1
l l → 1 l → 2
o 0 o → 1

The final frequency map is:

{
  h: 1,
  e: 1,
  l: 2,
  o: 1
}

Using Map for Character Frequency

JavaScript's Map provides another clean way to implement a frequency table. It is particularly useful when the keys may include different types or when explicit map operations make the algorithm easier to read.

function characterFrequency(text) {
  const frequency = new Map();

  for (const char of text) {
    const count = frequency.get(char) || 0;
    frequency.set(char, count + 1);
  }

  return frequency;
}

const result = characterFrequency("banana");

console.log(result);
// Map(3) { 'b' => 1, 'a' => 3, 'n' => 2 }

Ignoring Spaces and Punctuation

Some problems ask for the frequency of letters only. In that case, spaces and punctuation should not be counted. The input can be normalized before counting.

function letterFrequency(text) {
  const frequency = {};

  for (const char of text.toLowerCase()) {
    if (char >= "a" && char <= "z") {
      frequency[char] = (frequency[char] || 0) + 1;
    }
  }

  return frequency;
}

console.log(
  letterFrequency("Hello, World!")
);

// {
//   h: 1,
//   e: 1,
//   l: 3,
//   o: 2,
//   w: 1,
//   r: 1,
//   d: 1
// }

The exact normalization rules depend on the problem. Some applications may need to preserve uppercase and lowercase characters separately, while others may treat them as equivalent.

Case-Sensitive vs Case-Insensitive Counting

Character frequency is affected by whether uppercase and lowercase letters are treated as different characters.

const text = "AaA";

const frequency = {};

for (const char of text) {
  frequency[char] = (frequency[char] || 0) + 1;
}

console.log(frequency);

// {
//   A: 2,
//   a: 1
// }

If the requirement is case-insensitive, convert the input to lowercase or uppercase before building the frequency table.

Finding the Most Frequent Character

Once a frequency map has been created, it can be used to answer additional questions. For example, we can find the character with the highest frequency by iterating through the stored counts.

function mostFrequentCharacter(text) {
  const frequency = {};

  for (const char of text) {
    frequency[char] = (frequency[char] || 0) + 1;
  }

  let result = "";
  let maxCount = 0;

  for (const char in frequency) {
    if (frequency[char] > maxCount) {
      maxCount = frequency[char];
      result = char;
    }
  }

  return result;
}

console.log(mostFrequentCharacter("banana"));
// a

If multiple characters have the same maximum frequency, the result depends on the comparison and iteration rules used by the implementation. If a problem specifies a tie-breaking rule, that rule must be handled explicitly.

Finding the First Non-Repeating Character

A frequency map becomes particularly useful when combined with a second pass through the original string. First count every character, then scan the string again and return the first character whose frequency is one.

function firstNonRepeatingCharacter(text) {
  const frequency = {};

  for (const char of text) {
    frequency[char] = (frequency[char] || 0) + 1;
  }

  for (const char of text) {
    if (frequency[char] === 1) {
      return char;
    }
  }

  return null;
}

console.log(firstNonRepeatingCharacter("swiss"));
// w

Character Frequency and Anagrams

Character frequency is also a foundation for solving anagram problems. Two strings are anagrams when they contain the same characters with the same frequencies, assuming the problem uses the same normalization rules for both strings.

function areAnagrams(first, second) {
  if (first.length !== second.length) {
    return false;
  }

  const frequency = {};

  for (const char of first) {
    frequency[char] = (frequency[char] || 0) + 1;
  }

  for (const char of second) {
    if (!frequency[char]) {
      return false;
    }

    frequency[char]--;
  }

  return true;
}

console.log(areAnagrams("listen", "silent"));
// true

console.log(areAnagrams("hello", "world"));
// false

Frequency Counting with a Fixed Character Set

When the input is guaranteed to contain only a small, known character set, an array can sometimes be used instead of a hash map. For example, lowercase English letters can be mapped to indexes from 0 to 25.

function lowercaseLetterFrequency(text) {
  const frequency = new Array(26).fill(0);

  for (const char of text.toLowerCase()) {
    const index = char.charCodeAt(0) - "a".charCodeAt(0);

    if (index >= 0 && index < 26) {
      frequency[index]++;
    }
  }

  return frequency;
}

console.log(lowercaseLetterFrequency("banana"));

This approach uses a fixed-size array, but it depends on a known character range. A hash map is more flexible when the input can contain arbitrary characters.

Choosing Between Object, Map, and Array

Approach Best Fit Main Idea
Object Simple character keys Character becomes a property
Map General-purpose frequency mapping Explicit key-value storage
Array Small known character set Character mapped to numeric index

Complexity Analysis

Let n be the length of the input string and k be the number of distinct characters. Building the frequency map requires one pass through the string.

Task Time Space
Build frequency map O(n) average O(k)
Find most frequent character O(n + k) O(k)
First non-repeating character O(n) O(k)

For a fixed alphabet, such as lowercase English letters, the auxiliary space can be considered O(1) because the frequency array has a constant size. For arbitrary input, the number of distinct characters can grow with the input size.

Common Mistakes

  • Forgetting to initialize the count when a character appears for the first time.
  • Treating uppercase and lowercase characters as equivalent without normalizing the input.
  • Counting spaces and punctuation when the problem asks for letters only.
  • Using repeated string searches for every character and unnecessarily increasing the algorithm's time complexity.
  • Ignoring the required tie-breaking rule when multiple characters have the same frequency.

A Useful Problem-Solving Pattern

Character-frequency problems often follow a two-stage pattern: count first, then query the counts. The first pass builds the frequency table. A second pass or lookup then uses that information to answer the actual question.

Input
  ↓
Normalize if required
  ↓
Build frequency map
  ↓
Use counts to solve the problem
  ↓
Return the required result

Recognizing this pattern can make many string problems easier to solve because the frequency map separates counting from the final decision-making step.

Key Takeaways

  • Character frequency records how often each character occurs in a string.
  • A hash map is a common and flexible solution for frequency counting.
  • JavaScript objects and Map can both represent frequency tables.
  • A fixed-size array can be useful when the character set is known.
  • Frequency counting usually takes O(n) average time.
  • The frequency map can be reused for anagrams, duplicate detection, and other string problems.
  • Always clarify whether case, spaces, and punctuation should be counted.

Code Examples

function characterFrequency(text) {
  const frequency = {};

  for (const char of text) {
    frequency[char] = (frequency[char] || 0) + 1;
  }

  return frequency;
}

console.log(characterFrequency("banana"));

// {
//   b: 1,
//   a: 3,
//   n: 2
// }
    
function mostFrequentCharacter(text) {
  const frequency = {};

  for (const char of text) {
    frequency[char] = (frequency[char] || 0) + 1;
  }

  let result = "";
  let maxCount = 0;

  for (const char of text) {
    if (frequency[char] > maxCount) {
      maxCount = frequency[char];
      result = char;
    }
  }

  return result;
}

console.log(mostFrequentCharacter("banana"));
// a
    
function firstNonRepeatingCharacter(text) {
  const frequency = {};

  for (const char of text) {
    frequency[char] = (frequency[char] || 0) + 1;
  }

  for (const char of text) {
    if (frequency[char] === 1) {
      return char;
    }
  }

  return null;
}

console.log(firstNonRepeatingCharacter("swiss"));
// w
    

Pro Tip

When you see a string problem asking how often characters occur, think frequency map first. Build the counts in one pass, then use those counts to answer the actual question instead of repeatedly scanning the string.

🎨 IgKnight Docs

Master HTML, CSS, JS, Python, .NET and more with easy-to-follow lessons and practical code examples.

© 2025 IgKnight Learning Platform. All rights reserved.