Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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.*;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using wildcard imports (e.g., java.util.*). Please import only the specific classes you need.


// 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<>();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To use the Map and HashMap classes, you will need to import them:

import java.util.Map;
import java.util.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) -> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To use the PriorityQueue class, you will need to import it:

import java.util.PriorityQueue;

// Higher frequency comes first
int diff = b.getValue() - a.getValue();

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using a single-line if statement like:

if (diff == 0) return a.getKey() - b.getKey();

please use braces:

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.*;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using wildcard imports (e.g., org.junit.jupiter.api.Assertions.*). Please import only the specific classes you need.


import org.junit.jupiter.api.Test;

class SortCharacterByFrequencyTest {

private final SortCharacterByFrequency solution = new SortCharacterByFrequency();

@Test
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To use @Test annotation, you will need to import it:

import org.junit.jupiter.api.Test;

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

// Possible outputs: "eert" or "eetr"
assertTrue(result.equals("eert") || result.equals("eetr"));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To use assertTrue() method, you will need to import it:

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

}

@Test
void testSingleCharacter() {
assertEquals("a", solution.frequencySort("a"));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To use assertEquals() method, you will need to import it:

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

}

@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