Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Reference: https://leetcode.com/problems/sort-characters-by-frequency/
package com.thealgorithms.strings;
import java.util.*;

// Problem: Sort Characters By Frequency
// Pattern: HashMap + Priority Queue (Heap)
// Difficulty: Medium

/*
Approach:
1. Count frequency of each character using a HashMap.
2. Store characters in a max-heap (PriorityQueue) based on frequency.
3. If frequencies are same, sort by character (lexicographically).
4. Extract from heap and append characters 'frequency' times.

Time Complexity: O(n log n)
Space Complexity: O(n)
*/

class SortCharacterByFrequency {
public String frequencySort(String s) {

// Step 1: Count frequency of each character
Map<Character, Integer> map = new HashMap<>();

for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);

// Increment frequency using getOrDefault
map.put(ch, map.getOrDefault(ch, 0) + 1);
}

// Step 2: Create max-heap based on frequency
PriorityQueue<Map.Entry<Character, Integer>> pq = new PriorityQueue<>((a, b) -> {
// Higher frequency comes first
int diff = b.getValue() - a.getValue();

// If frequency same, sort by character
if (diff == 0) return a.getKey() - b.getKey();

return diff;
});

// Add all entries to heap
pq.addAll(map.entrySet());

// Step 3: Build result string
StringBuilder sb = new StringBuilder();

while (!pq.isEmpty()) {

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

char key = entry.getKey(); // character
int freq = entry.getValue(); // frequency

// Append character 'freq' times
for (int i = 0; i < freq; i++) {
sb.append(key);
}
}

// Step 4: Return final string
return sb.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.thealgorithms.strings;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

class SortCharacterByFrequencyTest {

private final SortCharacterByFrequency solution = new SortCharacterByFrequency();

@Test
void testBasicCase() {
String result = solution.frequencySort("tree");

// Possible outputs: "eert" or "eetr"
assertTrue(result.equals("eert") || result.equals("eetr"));
}

@Test
void testSingleCharacter() {
assertEquals("a", solution.frequencySort("a"));
}

@Test
void testEmptyString() {
assertEquals("", solution.frequencySort(""));
}

@Test
void testAllSameCharacters() {
assertEquals("aaaa", solution.frequencySort("aaaa"));
}

@Test
void testMixedCharacters() {
String result = solution.frequencySort("cccaaa");

// Possible outputs: "cccaaa" or "aaaccc"
assertTrue(result.equals("cccaaa") || result.equals("aaaccc"));
}

@Test
void testWithNumbersAndLetters() {
String result = solution.frequencySort("Aabb");

// 'b' appears twice → should come first
assertTrue(result.startsWith("bb"));
}
}
Loading