Sort Characters by Frequency

Java coding interview problem for Character Problems: Sort Characters by Frequency.

Sorting characters by frequency is one of the most popular String interview questions.

This problem combines two important concepts:

  • Frequency Counting
  • Sorting

It is frequently asked in coding interviews because it evaluates your understanding of:

  • HashMap
  • Sorting Algorithms
  • Comparator
  • Collections Framework
  • Priority Queue
  • Bucket Sort
  • Time Complexity

Many advanced interview problems are based on this concept, including:

  • Top K Frequent Elements
  • Top K Frequent Words
  • Character Frequency
  • Most Frequent Character
  • Group Anagrams
  • Huffman Coding

Mastering this problem makes many frequency-based interview questions much easier.


Problem Statement

Given a string,

sort all characters according to their frequency in descending order.

If two characters have the same frequency,

their relative order may depend on the interview requirement.

Always clarify whether:

  • Any order is acceptable.
  • Preserve insertion order.
  • Sort alphabetically when frequencies are equal.

Example 1

Input

tree

Output

eert

Explanation

e → 2

r → 1

t → 1

Example 2

Input

cccaaa

Output

cccaaa

or

aaaccc

Both are valid because

c → 3

a → 3

Example 3

Input

Aabb

Output

bbAa

Frequency

b → 2

A → 1

a → 1

Example 4

Input

banana

Output

aaannb

Frequency

a → 3

n → 2

b → 1

What is Frequency Sorting?

Instead of sorting alphabetically,

we sort based on

Frequency

Example

Input

banana

Alphabetical

aaabnn

Frequency Sorting

aaannb

because

a → 3

n → 2

b → 1

Another Example

Input

programming

Frequency

g → 2

r → 2

m → 2

others → 1

Characters having higher frequency appear first.


Why is this Question Asked in Interviews?

Interviewers use this question to evaluate:

  • HashMap
  • Sorting
  • Comparator
  • Collections Framework
  • Heap
  • Bucket Sort
  • Algorithm Design
  • Time Complexity

It combines multiple data structures in one problem.


Real-World Applications

Frequency sorting is widely used.


Search Engines

Sort frequently searched keywords.


Data Compression

Frequently occurring symbols receive shorter codes.

(Huffman Coding)


Text Analytics

Identify common characters.


Log Analysis

Detect repeated events.


Natural Language Processing

Analyze frequently occurring words and characters.


Recommendation Systems

Rank frequently used items.


Understanding Frequency Sorting

Input

banana

Step 1

Count frequencies

b → 1

a → 3

n → 2

Step 2

Sort

3

↓

2

↓

1

Step 3

Build answer

aaa

↓

nn

↓

b

Final

aaannb

Frequency Table Visualization

Input

banana
Character Frequency
a 3
n 2
b 1

Sorted

a

↓

n

↓

b

Another Example

Input

tree
Character Frequency
e 2
t 1
r 1

Sorted

e

↓

t

↓

r

Mathematical Concept

Frequency

Frequency(Character)

=

Occurrences

Sorting

Highest Frequency

↓

Lowest Frequency

Example

1

3

2

Sorted

3

↓

2

↓

1

ASCII Visualization

Input

banana
a

↓

3
n

↓

2
b

↓

1

Output

aaa

↓

nn

↓

b

Dry Run

Input

tree

Frequency Map

t → 1

r → 1

e → 2

Sort

e → 2

t → 1

r → 1

Build String

ee

↓

t

↓

r

Output

eetr

Approach 1 — Using HashMap + List Sorting (Recommended)

This is the most common interview solution.

The idea is simple:

  1. Count frequencies using a HashMap.
  2. Store entries inside a List.
  3. Sort the list by frequency.
  4. Build the answer.

Algorithm

  1. Create HashMap.
  2. Count frequencies.
  3. Convert map into a List.
  4. Sort descending by frequency.
  5. Append each character frequency times.
  6. Return the string.

Java Program

import java.util.*;

public class SortCharactersByFrequency {

    public static String frequencySort(String text) {

        Map<Character, Integer> map =
                new HashMap<>();

        for (char ch : text.toCharArray()) {

            map.put(ch,
                    map.getOrDefault(ch, 0) + 1);

        }

        List<Map.Entry<Character, Integer>> list =
                new ArrayList<>(map.entrySet());

        list.sort((a, b) ->
                b.getValue() - a.getValue());

        StringBuilder result =
                new StringBuilder();

        for (Map.Entry<Character, Integer> entry : list) {

            for (int i = 0;
                 i < entry.getValue();
                 i++) {

                result.append(entry.getKey());

            }

        }

        return result.toString();

    }

    public static void main(String[] args) {

        System.out.println(
                frequencySort("banana"));

    }

}

Output

aaannb

Step-by-Step Code Explanation

Create HashMap

Map<Character,Integer> map =
        new HashMap<>();

Count frequencies

map.put(ch,
        map.getOrDefault(ch,0)+1);

Convert into List

new ArrayList<>(map.entrySet())

Sort descending

list.sort(...)

Append characters

Example

a → 3

Append

aaa

Repeat for every entry.


Return

result.toString()

Dry Run of HashMap Approach

Input

apple

Frequency

a → 1

p → 2

l → 1

e → 1

Sorted

p

↓

a

↓

l

↓

e

Output

ppale

Advantages

  • Most common interview solution.
  • Easy to understand.
  • Supports Unicode.
  • Highly flexible.
  • Uses Java Collections Framework.

Drawbacks

  • Requires additional sorting.
  • Extra memory for List.
  • Comparator introduces slight overhead.

Approach 2 — Using Frequency Array + Sorting (ASCII)

If the input contains only ASCII characters,

a Frequency Array is slightly faster than HashMap.


Visualization

Input

banana

Frequency Array

a

↓

3
n

↓

2
b

↓

1

Sort

3

↓

2

↓

1

Algorithm

  1. Create frequency array.
  2. Count characters.
  3. Store character-frequency pairs.
  4. Sort descending.
  5. Build final string.

Java Program

import java.util.*;

public class FrequencyArraySorting {

    public static String frequencySort(String text) {

        int[] frequency =
                new int[256];

        for (char ch : text.toCharArray()) {

            frequency[ch]++;

        }

        List<Character> characters =
                new ArrayList<>();

        for (int i = 0; i < 256; i++) {

            if (frequency[i] > 0) {

                characters.add((char) i);

            }

        }

        characters.sort((a, b) ->
                frequency[b] - frequency[a]);

        StringBuilder result =
                new StringBuilder();

        for (char ch : characters) {

            for (int i = 0;
                 i < frequency[ch];
                 i++) {

                result.append(ch);

            }

        }

        return result.toString();

    }

    public static void main(String[] args) {

        System.out.println(
                frequencySort("banana"));

    }

}

Output

aaannb

Step-by-Step Code Explanation

Create frequency array.

int[] frequency =
        new int[256];

Count characters.

frequency[ch]++;

Collect used characters.

characters.add(...)

Sort

characters.sort(...)

Build answer.

Append each character according to its frequency.


Time & Space Complexity

Approach Time Extra Space
HashMap + Sorting O(n + k log k) O(k)
Frequency Array + Sorting O(n + k log k) O(1)*

Where

  • n = Length of the string
  • k = Number of distinct characters

*For a fixed ASCII character set, the array size (256) is constant, so the extra space is considered O(1).


Comparison of Approaches

Feature HashMap + Sorting Frequency Array
Interview Friendly ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Performance ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Unicode Support ✅ ❌
ASCII Optimization ❌ ✅

Advantages

  • Both approaches are efficient and widely accepted.
  • HashMap supports Unicode and dynamic character sets.
  • Frequency Array is optimized for ASCII input.
  • Both produce correct frequency-sorted output.

Drawbacks

  • Both require sorting after frequency counting.
  • HashMap requires additional memory.
  • Frequency Array is limited to ASCII characters.

Approach 3 — Using Priority Queue (Max Heap)

A Priority Queue (Max Heap) always removes the character with the highest frequency first.

This approach is widely used in interview problems like:

  • Top K Frequent Elements
  • Top K Frequent Words
  • Rearrange String
  • Task Scheduler

Why Priority Queue?

Instead of sorting the entire list,

we insert every character into a Max Heap.

The heap automatically keeps the highest frequency character at the top.


Algorithm

  1. Count frequencies using HashMap.
  2. Insert all map entries into a Max Heap.
  3. Remove the highest frequency character.
  4. Append it frequency times.
  5. Repeat until the heap is empty.

Java Program

import java.util.*;

public class FrequencySortPriorityQueue {

    public static String frequencySort(String text) {

        Map<Character, Integer> map = new HashMap<>();

        for (char ch : text.toCharArray()) {
            map.put(ch, map.getOrDefault(ch, 0) + 1);
        }

        PriorityQueue<Map.Entry<Character, Integer>> pq =
                new PriorityQueue<>(
                        (a, b) -> b.getValue() - a.getValue());

        pq.addAll(map.entrySet());

        StringBuilder result = new StringBuilder();

        while (!pq.isEmpty()) {

            Map.Entry<Character, Integer> entry = pq.poll();

            for (int i = 0; i < entry.getValue(); i++) {
                result.append(entry.getKey());
            }

        }

        return result.toString();

    }

    public static void main(String[] args) {

        System.out.println(frequencySort("banana"));

    }

}

Output

aaannb

Advantages

  • Excellent for Top-K problems.
  • Easy to extend.
  • Efficient removal of highest-frequency characters.

Drawbacks

  • Slight heap overhead.
  • Requires additional memory.

Approach 4 — Using Java Streams

Java 8 Streams provide a concise functional programming solution.

The idea is:

  • Count frequencies
  • Convert to Stream
  • Sort by frequency
  • Build the answer

Algorithm

  1. Count frequencies.
  2. Convert entries into a Stream.
  3. Sort descending.
  4. Repeat characters.
  5. Join into a string.

Java Program

import java.util.*;
import java.util.stream.Collectors;

public class FrequencySortStreams {

    public static String frequencySort(String text) {

        Map<Character, Integer> map = new HashMap<>();

        for (char ch : text.toCharArray()) {
            map.put(ch, map.getOrDefault(ch, 0) + 1);
        }

        return map.entrySet()
                .stream()
                .sorted((a, b) ->
                        b.getValue().compareTo(a.getValue()))
                .map(entry ->
                        String.valueOf(entry.getKey())
                                .repeat(entry.getValue()))
                .collect(Collectors.joining());

    }

    public static void main(String[] args) {

        System.out.println(frequencySort("banana"));

    }

}

Output

aaannb

Advantages

  • Modern Java.
  • Very concise.
  • Easy to combine with other Stream operations.

Drawbacks

  • Harder for beginners.
  • Slight Stream overhead.
  • Less common in interviews.

Approach 5 — Using Bucket Sort (Optimal)

Bucket Sort is the optimal solution for this problem.

Instead of sorting characters,

we place characters into buckets based on their frequencies.


Why Bucket Sort?

The maximum frequency of any character cannot exceed

String Length (n)

Therefore,

we create

n + 1

buckets.

Each bucket stores all characters having the same frequency.


Visualization

Input

banana

Frequency

a → 3

n → 2

b → 1

Buckets

Bucket[3]

↓

a
Bucket[2]

↓

n
Bucket[1]

↓

b

Read buckets from highest to lowest.

Output

aaannb

Algorithm

  1. Count frequencies.
  2. Create buckets.
  3. Place each character into its frequency bucket.
  4. Traverse buckets from highest to lowest.
  5. Append characters.

Java Program

import java.util.*;

public class FrequencySortBucket {

    public static String frequencySort(String text) {

        Map<Character, Integer> map = new HashMap<>();

        for (char ch : text.toCharArray()) {
            map.put(ch, map.getOrDefault(ch, 0) + 1);
        }

        List<Character>[] buckets =
                new ArrayList[text.length() + 1];

        for (Map.Entry<Character, Integer> entry : map.entrySet()) {

            int frequency = entry.getValue();

            if (buckets[frequency] == null) {
                buckets[frequency] = new ArrayList<>();
            }

            buckets[frequency].add(entry.getKey());

        }

        StringBuilder result = new StringBuilder();

        for (int i = buckets.length - 1; i >= 1; i--) {

            if (buckets[i] == null)
                continue;

            for (char ch : buckets[i]) {

                for (int j = 0; j < i; j++) {
                    result.append(ch);
                }

            }

        }

        return result.toString();

    }

    public static void main(String[] args) {

        System.out.println(frequencySort("banana"));

    }

}

Output

aaannb

Advantages

  • Optimal solution.
  • No explicit sorting.
  • Excellent interview discussion point.
  • Very efficient for large inputs.

Drawbacks

  • Slightly harder to understand.
  • Requires bucket array.
  • More implementation code.

Unicode Considerations

Java uses UTF-16 for String.

Examples

こんにちは
नमस्ते
😊😊😊

HashMap, Priority Queue, Streams, and Bucket Sort

✅ Support Unicode because they work with Java char values.

Frequency Array

❌ Limited to the chosen array size (typically ASCII 256).


Edge Cases

Input Output
"" ""
"a" a
"aaaa" aaaa
"abc" abc (or any order if frequencies are equal)
"112233" Any valid frequency-sorted order
"😊😊😊a" Requires Unicode-aware handling

Time & Space Complexity

Approach Time Extra Space
HashMap + Sorting O(n + k log k) O(k)
Frequency Array + Sorting O(n + k log k) O(1)*
Priority Queue O(n + k log k) O(k)
Java Streams O(n + k log k) O(k)
Bucket Sort O(n) O(n)

Where

  • n = Length of the string
  • k = Number of distinct characters

*For a fixed ASCII character set, the frequency array occupies constant space.


Comparison of All Approaches

Approach Interview Friendly Performance Unicode Support Best Use Case
HashMap + Sorting ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ✅ Standard interview solution
Frequency Array ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ❌ ASCII-only strings
Priority Queue ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ✅ Top-K frequency problems
Java Streams ⭐⭐⭐⭐ ⭐⭐⭐ ✅ Modern Java
Bucket Sort ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ✅ Optimal solution for frequency sorting

Common Interview Mistakes

Mistake 1

Sorting alphabetically instead of by frequency.

Wrong

aaabnn

Correct

aaannb

Mistake 2

Ignoring characters with equal frequencies.

Clarify whether:

  • Any order is acceptable.
  • Alphabetical order is required.
  • Stable ordering is expected.

Mistake 3

Using String concatenation inside loops.

Wrong

result += ch;

Correct

StringBuilder result = new StringBuilder();

Mistake 4

Not considering Unicode.

ASCII arrays fail for many international characters.


Mistake 5

Sorting the original string instead of sorting by frequency.

Frequency sorting and alphabetical sorting are different problems.


Interview Follow-up Questions

Q1. Why is HashMap used?

Q2. Why is Bucket Sort O(n)?

Q3. Why is Priority Queue useful?

Q4. Which solution supports Unicode?

Q5. Can Bucket Sort replace sorting?

Q6. What happens when frequencies are equal?

Q7. Which solution is best for Top-K problems?

Q8. Why use StringBuilder?

Q9. Can Streams improve readability?

Q10. How would you process a string with millions of characters?


Related Problems

  • Character Frequency
  • Most Frequent Character
  • Top K Frequent Elements
  • Top K Frequent Words
  • Group Anagrams
  • Huffman Coding
  • First Non-Repeating Character
  • Sort Array by Frequency
  • Rearrange String K Distance Apart

Key Takeaways

  • Frequency sorting combines HashMap and Sorting concepts.
  • HashMap + List Sorting is the most common interview solution.
  • Frequency Array is a fast optimization for ASCII input.
  • Priority Queue is ideal for Top-K frequency-based problems.
  • Java Streams provide a clean functional implementation.
  • Bucket Sort is the optimal approach with O(n) time complexity.

Frequently Asked Interview Questions

Q1. Which solution is best for interviews?

HashMap + List Sorting is the safest and most commonly expected solution.


Q2. Which solution is fastest?

Bucket Sort achieves O(n) time complexity because it avoids comparison-based sorting.


Q3. Why use Priority Queue?

It efficiently retrieves the highest-frequency character and is easily extended to Top-K problems.


Q4. Why use StringBuilder?

StringBuilder avoids creating multiple immutable String objects, making repeated appends much more efficient.


Q5. Can Bucket Sort handle Unicode?

Yes. When combined with a HashMap, Bucket Sort works with Unicode characters because the frequencies are stored independently of character encoding.


Interview Tip

If an interviewer asks:

"Sort characters by frequency in a string."

Start with the HashMap + List Sorting solution because it is simple, readable, and demonstrates strong knowledge of Java Collections.

Then discuss progressively more advanced approaches:

  1. HashMap + List Sorting (recommended)
  2. Frequency Array + Sorting (ASCII optimization)
  3. Priority Queue (Max Heap)
  4. Java Streams (functional style)
  5. Bucket Sort (optimal O(n) solution)

Also clarify these requirements before coding:

  • Should equal-frequency characters preserve insertion order?
  • Is alphabetical ordering required for ties?
  • Does the input include Unicode characters?
  • Can additional memory be used?

Showing multiple approaches and discussing their trade-offs demonstrates a strong understanding of algorithms, data structures, and Java best practices.