#387 First Unique Character in a String
frequently reported atGoldman SachsBloombergWalmartAmazonApple
the problem
In plain words
s contains only lowercase letters. Find the first character that appears exactly once in the whole string and return its index. If every character repeats, return -1.
in s = "leetcode"
out 0
'l' appears only once.
in s = "loveleetcode"
out 2
'l' and 'o' repeat; 'v' at index 2 doesn't.
in s = "aabb"
out -1
- 1 ≤ s.length ≤ 10⁵
- Lowercase English letters only
your turn
Try it before you peek
Read the examples, say the brute force out loud, then write code: here or on LeetCode ↗. Stuck for 20 minutes? Open one hint at a time.
Solve it in the browser
LeetCode-style: complete the class. Compiled by the real javac (Java 17) and judged right here — nothing is sent anywhere.
Solutions are hidden so you can try first. Even 20 minutes of real effort makes the answer stick far better than reading it.
Marking the problem solved, or opening every hint, also shows it.
the aha
Key insight
patternFrequency counting
"Appears once" needs the whole string; "first" needs the order. So two passes: count everything, then walk s in order and return the first letter whose count is 1.
solutions
From brute force to optimal
For each position, scan the string for the same letter somewhere else.
- For each i, loop j over the string (j ≠ i).
- If s[j] == s[i], it repeats — move on.
- The first i with no match is the answer.
Up to n scans of n chars — 10¹⁰ steps at n = 10⁵.
Two indexes.
class Solution { public int firstUniqChar(String s) { for (int i = 0; i < s.length(); i++) { boolean repeated = false; for (int j = 0; j < s.length(); j++) { if (j != i && s.charAt(j) == s.charAt(i)) { // same letter somewhere else repeated = true; break; } } if (!repeated) return i; } return -1; }}Count letters in a HashMap<Character, Integer>, then scan in order.
count.merge(c, 1, Integer::sum)for every char.- Return the first i with
count.get(s.charAt(i)) == 1.
Two passes, O(1) average per map operation.
At most 26 keys — but each key and value is a boxed object.
class Solution { public int firstUniqChar(String s) { Map<Character, Integer> count = new HashMap<>(); for (char c : s.toCharArray()) count.merge(c, 1, Integer::sum); // boxes c and the count for (int i = 0; i < s.length(); i++) { if (count.get(s.charAt(i)) == 1) return i; // Integer == int unboxes: safe here } return -1; }}Same two passes, but c - 'a' turns each letter into an index of a plain array.
- count = new int[26].
- Pass 1: count[s[i] − 'a']++.
- Pass 2: first i with count[s[i] − 'a'] == 1.
- Otherwise −1.
Two passes of array increments — no hashing, no boxing.
26 ints, whatever the length of s.
class Solution { public int firstUniqChar(String s) { int[] count = new int[26]; // one counter per letter for (int i = 0; i < s.length(); i++) { count[s.charAt(i) - 'a']++; // 'a'->0 ... 'z'->25 } for (int i = 0; i < s.length(); i++) { // second pass, in string order if (count[s.charAt(i) - 'a'] == 1) { // seen exactly once? return i; } } return -1; // every letter repeats }}Dry run
in the room
How to say it in the interview
talk track
- Clarify: lowercase only? (Yes — that's what allows
int[26].) - Mention the O(n²) idea in one line, then the two-pass count: O(n) time, O(1) space because the alphabet is fixed.
- Explain why pass 2 walks s and not the count array: the count array is in alphabet order, the answer needs string order.
traps
- Walking the count array in pass 2 returns the alphabetically first unique letter, not the first one in s.
c - 'a'on an uppercase letter or digit goes negative →ArrayIndexOutOfBoundsException.
what they ask next
Follow-ups
Characters arrive as a stream and you must answer after each one?
Keep the counts plus a queue of candidates; after each char, pop from the front while the front's count is above 1. Each char enters and leaves once: O(1) amortised.
Full Unicode instead of a–z?
Use a HashMap<Character, Integer> — the two-pass idea doesn't change.
before you submit
Edge cases to test
- No unique letter ("aabb") → −1.
- The unique letter is the very last one ("aabbc") → 4.
- A single character → 0.
practise next
Similar problems
- #242Valid AnagramEasyin Arrays & Strings
- #1636Sort Array by Increasing FrequencyEasyin Sorting
- #3Longest Substring Without Repeating CharactersMediumin Sliding Window