First Unique Character in a String

Easy Hash Maps

Problem

Given a string s, return the index of the first non-repeating character in it. If it does not exist, return -1.

  • 1 ≤ s.length ≤ 10⁵
  • s consists of only lowercase English letters

Example

Input: s = "leetcode"
Output: 0

The character 'l' appears only once and is the first such character in the string. The algorithm counts the frequency of each character: {'l':1, 'e':3, 't':1, 'c':1, 'o':1, 'd':1}. Then it scans the string from left to right, returning the index of the first character with count 1, which is index 0.

Approach

Straightforward Solution

A naive approach would check each character and scan the entire string to count its occurrences, resulting in O(n^2) time complexity, which is inefficient for large inputs.

Core Observation

The problem reduces to identifying the first character in the string whose frequency is exactly one. This requires counting occurrences and then scanning for the earliest unique character.

Path to Optimal

The key insight is to use a hash map (dictionary) to count the frequency of each character in a single pass, which takes O(n) time. Then, a second pass through the string checks the stored counts to find the first character with count one. This two-pass approach reduces the time complexity to O(n).

Optimal Approach

Use a hash map to count frequencies in one pass over the string. Then iterate over the string again, returning the index of the first character with frequency one. If none exists, return -1. This approach is efficient and straightforward, with O(n) time and O(1) space since the character set is limited to lowercase English letters.

Time

O(n)

The algorithm makes two passes over the string of length n: one to count frequencies and one to find the first unique character. Each hash map operation is O(1) on average.

Space

O(1)

The hash map stores counts for at most 26 lowercase English letters, which is constant space independent of input size.

Pattern Spotlight

Hash Maps (Frequency Counting)

When needing to identify unique or duplicate elements efficiently, use a hash map to count occurrences in one pass, then use a second pass to find the first element meeting the uniqueness criteria, enabling O(n) time complexity.

Solution

1class Solution:
2 def firstUniqChar(self, s: str) -> int:
3
4 count = {}
5
6 for c in s:
7 count[c] = count.get(c, 0) + 1
8
9 for i in range(len(s)):
10 if count[s[i]] == 1:
11 return i
12
13 return -1

Step-by-Step Solution

1

Count Frequencies of All Characters in the String

4count = {}
6for c in s:
7 count[c] = count.get(c, 0) + 1

Objective

To build a frequency map that records how many times each character appears in the string.

Key Insight

Counting frequencies in a single pass allows the algorithm to gather all necessary information about character occurrences efficiently. Using a hash map keyed by characters provides O(1) average insertion and lookup, enabling a linear time solution.

Interview Quick-Check

Core Logic

Use a hash map to count each character's occurrences in one pass, enabling constant-time frequency lookups later.

Complexity

This step runs in O(n) time, where n is the length of the string.

Common Pitfalls & Bugs

Forgetting to initialize counts properly or using a data structure with slower lookups can degrade performance.

2

Identify and Return the Index of the First Unique Character

9for i in range(len(s)):
10 if count[s[i]] == 1:
11 return i
13return -1

Objective

To scan the string and find the earliest character whose frequency is exactly one.

Key Insight

By leveraging the precomputed frequency map, the algorithm can quickly check each character's count in order, returning the first index where the count is one. This avoids redundant counting and ensures the earliest unique character is found efficiently.

Interview Quick-Check

Core Logic

Iterate over the string and use the frequency map to identify the first character with count one.

State & Boundaries

Return -1 if no unique character exists, ensuring correct handling of edge cases.

Common Pitfalls & Bugs

Failing to return immediately upon finding the first unique character can lead to incorrect results or unnecessary computation.

Line Analysis

This solution has 2 Critical lines interviewers watch for.

Line 4 Critical
count = {}

Initialize an empty dictionary to count character frequencies.

This dictionary serves as the frequency map, enabling O(1) average-time updates and lookups for each character.

Line 6 Critical
for c in s:

Iterate over each character in the string.

This loop performs a single pass to gather frequency information for all characters.

Line 7 Standard
count[c] = count.get(c, 0) + 1

Increment the count for the current character in the frequency map.

Updating counts in the hash map accumulates the total occurrences of each character efficiently.

Line 9 Standard
for i in range(len(s)):

Iterate over the string indices to check character frequencies in order.

This loop ensures the earliest unique character is found by scanning from left to right.

Line 10 Standard
if count[s[i]] == 1:

Check if the current character's frequency is exactly one.

This condition identifies unique characters, which are candidates for the answer.

Line 11 Standard
return i

Return the index of the first unique character found.

Returning immediately upon finding the first unique character guarantees the earliest index is returned.

Line 13 Standard
return -1

Return -1 if no unique character exists in the string.

This return value correctly signals that the string contains no non-repeating characters.

Test Your Understanding

Why is it necessary to perform two passes over the string instead of just one?

Because the frequency of each character must be known before determining which character is unique and appears first. The first pass collects counts, and the second pass uses these counts to identify the earliest unique character.

Related Problems

Hash Maps pattern

Don't just read it. Drill it.

Reconstruct First Unique Character in a String from memory until it sticks. AlgoDrill blanks out key lines and makes you fill them back in, step by step.

Unlock the First Unique Character in a String drill

or drill a free problem