🧠
Using Frequency Map + Queue
💡 This approach improves efficiency by tracking frequencies and maintaining a queue of candidates for first unique character.
Intuition
Keep a frequency map to count occurrences and a queue to store characters that might be unique. Remove characters from the queue front if they are no longer unique.
Algorithm
- Initialize a frequency map and an empty queue.
- For each incoming character, increment its frequency.
- Add the character to the queue if it's the first time seen.
- While the queue front character frequency is more than 1, dequeue it.
- The front of the queue is the first unique character; if empty, return '#'.
💡 The key insight is that the queue always holds candidates for first unique, so we only check the front.
from collections import deque
def first_unique_stream(stream):
freq = {}
q = deque()
result = []
for ch in stream:
freq[ch] = freq.get(ch, 0) + 1
if freq[ch] == 1:
q.append(ch)
while q and freq[q[0]] > 1:
q.popleft()
result.append(q[0] if q else '#')
return result
# Driver code
if __name__ == '__main__':
stream = ['a', 'b', 'c', 'a', 'c', 'b', 'd']
print(first_unique_stream(stream)) # Expected: ['a', 'a', 'a', 'b', 'b', '#', 'd']
Line Notes
freq[ch] = freq.get(ch, 0) + 1Update frequency count for current character
if freq[ch] == 1:Add character to queue only if first occurrence
while q and freq[q[0]] > 1:Remove characters from queue front if repeated
result.append(q[0] if q else '#')Append first unique or '#' if none
import java.util.*;
public class FirstUniqueStream {
public static List<Character> firstUniqueStream(char[] stream) {
Map<Character, Integer> freq = new HashMap<>();
Queue<Character> q = new LinkedList<>();
List<Character> result = new ArrayList<>();
for (char ch : stream) {
freq.put(ch, freq.getOrDefault(ch, 0) + 1);
if (freq.get(ch) == 1) {
q.offer(ch);
}
while (!q.isEmpty() && freq.get(q.peek()) > 1) {
q.poll();
}
result.add(q.isEmpty() ? '#' : q.peek());
}
return result;
}
public static void main(String[] args) {
char[] stream = {'a', 'b', 'c', 'a', 'c', 'b', 'd'};
System.out.println(firstUniqueStream(stream)); // Expected: [a, a, a, b, b, #, d]
}
}
Line Notes
freq.put(ch, freq.getOrDefault(ch, 0) + 1);Increment frequency count for character
if (freq.get(ch) == 1)Add character to queue only if first time seen
while (!q.isEmpty() && freq.get(q.peek()) > 1)Remove repeated characters from queue front
result.add(q.isEmpty() ? '#' : q.peek());Add first unique or '#' if none
#include <iostream>
#include <vector>
#include <unordered_map>
#include <queue>
using namespace std;
vector<char> firstUniqueStream(const vector<char>& stream) {
unordered_map<char, int> freq;
queue<char> q;
vector<char> result;
for (char ch : stream) {
freq[ch]++;
if (freq[ch] == 1) {
q.push(ch);
}
while (!q.empty() && freq[q.front()] > 1) {
q.pop();
}
result.push_back(q.empty() ? '#' : q.front());
}
return result;
}
int main() {
vector<char> stream = {'a', 'b', 'c', 'a', 'c', 'b', 'd'};
vector<char> res = firstUniqueStream(stream);
for (char c : res) cout << c << ' ';
cout << endl; // Expected: a a a b b # d
return 0;
}
Line Notes
freq[ch]++;Increment frequency count for character
if (freq[ch] == 1)Add character to queue only if first occurrence
while (!q.empty() && freq[q.front()] > 1)Remove repeated characters from queue front
result.push_back(q.empty() ? '#' : q.front());Append first unique or '#' if none
function firstUniqueStream(stream) {
const freq = {};
const q = [];
const result = [];
for (const ch of stream) {
freq[ch] = (freq[ch] || 0) + 1;
if (freq[ch] === 1) {
q.push(ch);
}
while (q.length && freq[q[0]] > 1) {
q.shift();
}
result.push(q.length ? q[0] : '#');
}
return result;
}
// Driver code
const stream = ['a', 'b', 'c', 'a', 'c', 'b', 'd'];
console.log(firstUniqueStream(stream)); // Expected: ['a', 'a', 'a', 'b', 'b', '#', 'd']
Line Notes
freq[ch] = (freq[ch] || 0) + 1;Update frequency count for character
if (freq[ch] === 1)Add character to queue only if first occurrence
while (q.length && freq[q[0]] > 1)Remove repeated characters from queue front
result.push(q.length ? q[0] : '#');Append first unique or '#' if none
Each character is enqueued and dequeued at most once, so total operations are linear in n. Frequency map uses O(n) space.
💡 For n=100000, this approach can handle the input efficiently within time limits.
Interview Verdict: Accepted / Optimal for interview coding
This approach balances clarity and efficiency, making it ideal to implement in interviews.