Java ProgramsStringsFind Least Frequent Character in a String

Find Least Frequent Character in a String in Java

intermediate·  Strings  ·  String

Problem

The least frequent character is whichever character has the lowest count once every character's occurrences have been tallied.

Given a string, find the character that appears the fewest times, along with its count.

Input
success
Output
Least frequent character: u (1 time)

Java Program

Java
import java.util.LinkedHashMap; import java.util.Map; public class LeastFrequentCharacter { public static void main(String[] args) { String str = "success"; Map<Character, Integer> freq = new LinkedHashMap<>(); for (char c : str.toCharArray()) { freq.put(c, freq.getOrDefault(c, 0) + 1); // increment this character's running count } Character minChar = null; int minCount = Integer.MAX_VALUE; for (Map.Entry<Character, Integer> entry : freq.entrySet()) { if (entry.getValue() < minCount) { // found a new lowest count so far minChar = entry.getKey(); minCount = entry.getValue(); } } System.out.println("Least frequent character: " + minChar + " (" + minCount + " time)"); } }

Output

Least frequent character: u (1 time)

Core Logic

Building the frequency map first, then scanning it once for the lowest count, is the mirror image of finding the most frequent character.

How It Works
  1. 1A LinkedHashMap<Character, Integer> named freq tracks each character's count, exactly like counting character frequency.
  2. 2freq.getOrDefault(c, 0) reads the current count, or 0 if unseen, then freq.put(c, ...) stores the incremented count.
  3. 3minChar and minCount start at the first entry's character and count, then walk the rest of entrySet().
  4. 4Whenever an entry's count is lower than minCount, both minChar and minCount are updated to that entry.
In "success", 'u' and 'e' both appear once — the fewest of any character — and 'u' wins since it's encountered first.
💡

Key Point: Starting minCount from the first entry, rather than from a sentinel like Integer.MAX_VALUE, guarantees a valid character is always reported, even for a string with only one distinct character.

Complexity
Time Complexity: O(n)Space Complexity: O(n)

Why: Building the frequency map visits every character once and holds one entry per distinct character, up to n in the worst case.

Key Concepts

LinkedHashMapgetOrDefault()running minimum

Approach 2: Java 8

Java
import java.util.LinkedHashMap; import java.util.Map; import java.util.stream.Collectors; public class LeastFrequentCharacterStream { public static void main(String[] args) { String str = "success"; Map<Character, Long> freq = str.chars() .mapToObj(c -> (char) c) .collect(Collectors.groupingBy(c -> c, LinkedHashMap::new, Collectors.counting())); // Compares every entry by its count and keeps the smallest one Map.Entry<Character, Long> minEntry = freq.entrySet().stream() .min(Map.Entry.comparingByValue()) .orElseThrow(); System.out.println("Least frequent character: " + minEntry.getKey() + " (" + minEntry.getValue() + " time)"); } }

Output

Least frequent character: u (1 time)

Core Logic

Once the frequency map exists, a stream can find its lowest-valued entry directly instead of a manual running-minimum loop.

How It Works
  1. 1str.chars().mapToObj(c -> (char) c) turns the string's character codes into a Stream<Character>.
  2. 2Collectors.groupingBy(c -> c, LinkedHashMap::new, Collectors.counting()) groups equal characters and counts each group, in first-appearance order.
  3. 3freq.entrySet().stream().min(Map.Entry.comparingByValue()) compares every entry by its count and keeps the single smallest one.
  4. 4.orElseThrow() unwraps the result from the Optional it's wrapped in.
Grouping "success" produces counts for each character, and min() picks out 'u': 1 as the smallest entry, matching the manual version's first-seen tiebreak.
💡

Key Point: Using LinkedHashMap::new as the map factory keeps ties resolved the same way as the manual loop — min() keeps the first minimum it encounters while scanning entries in insertion order.

Complexity
Time Complexity: O(n)Space Complexity: O(n)

Why: groupingBy() still visits every character once to build the map, and min() then makes one pass over its entries to find the smallest.

Key Concepts

StreamCollectors.groupingBy()Map.Entry.comparingByValue()

Related Programs