Most Frequent Character in a String | Geeks For Geeks Classic.

When I first saw the problem “Find the most frequent character in a string” on GeeksforGeeks, my initial thought was - “Oh, this looks simple, I can just count and pick the max.” But as I started coding, I realized there’s a little twist - if two characters have the same frequency, then I need to return the lexicographically smaller character.
Let’s solve this together.
Step 1: The Naive Approach - Using Counter
Like most of us, my first instinct was to use Python’s built-in collections.Counter.
from collections import Counter
def getMaxOccurringChar(s):
freq = Counter(s)
return max(freq, key=freq.get)
print(getMaxOccurringChar("output"))
At first glance, this looks fine. It gives us the most frequent character.
But there’s a catch, in "output", both 't' and 'u' appear twice.max()
will just pick whichever it sees first, not the lexicographically smaller one.
So the answer should be 't', but my function could fail.
Step 2: Adding Lexicographic Ordering
To fix this, I thought - “Why not sort the characters alphabetically before checking frequency? That way, in case of a tie, the lexicographically smaller one comes first.”
Here’s the code:
def getMaxOccurringChar(s):
freq = {}
# Step 1: Frequency map
for ch in s:
if ch not in freq:
freq[ch] = 1
else:
freq[ch] += 1
# Step 2: Sort by character (lexicographically)
freq = dict(sorted(freq.items()))
maxi = 0
res = None
# Step 3: Find max frequency character
for key, value in freq.items():
if maxi < value:
maxi = value
res = key
return res
print(getMaxOccurringChar("test")) # t
print(getMaxOccurringChar("output")) # t
Now it works
Step 3: Optimized Approach Without Sorting
Sorting gives the right answer, but adds unnecessary O(K log K)
complexity (K = distinct characters).
So I improved it further: while scanning, if two characters have the same frequency, just compare them directly.
def getMaxOccurringChar(s):
freq = {}
# Step 1: Build frequency map
for ch in s:
freq[ch] = freq.get(ch, 0) + 1
# Step 2: Track max freq + lexicographically smallest
maxi = 0
res = None
for key in freq:
if freq[key] > maxi or (freq[key] == maxi and key < res):
maxi = freq[key]
res = key
return res
print(getMaxOccurringChar("test")) # t
print(getMaxOccurringChar("output")) # t
This directly enforces the condition:
Higher frequency → update.
Same frequency → check lexicographically smaller.
Time & Space Complexity
Approach 1: Using Counter
only
Time Complexity:
O(N)
for counter +O(K)
for scan.Fails for lexicographic condition without extra handling.
Approach 2: Sorting + Dictionary
Time Complexity:
O(N + K log K)
Space Complexity:
O(K)
Approach 3: Optimized Dictionary (Best)
Time Complexity:
O(N + K)
(practicallyO(N)
)Space Complexity:
O(K)
Final Thoughts
What I really liked about this problem was how a “simple” task of finding the most frequent character actually pushed me to think about edge cases like lexicographic ordering.
First, I rushed with “Counter”.
Then I realized I needed sorting.
Finally, I optimized it with direct comparisons.
Lesson learned: Don’t stop at the first working solution. Always refine and check edge cases like ties, because that’s where your logic is truly tested.
Subscribe to my newsletter
Read articles from Prashant Gupta directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
