Given a string s consisting of only lowercase alphabets, for each index i in the string (0 ≤ i < n), find the first non-repeating character in the prefix s[0..i]. If no such character exists, use '#'.
Examples:
Input: s = "aabc"
Output: a#bb
Explanation:
At i=0 ("a"): First non-repeating character is 'a'.
At i=1 ("aa"): No non-repeating character, so '#'.
At i=2 ("aab"): First non-repeating character is 'b'.
At i=3 ("aabc"): Non-repeating characters are 'b' and 'c'; 'b' appeared first, so 'b'.Input: s = "bb"
Output: "b#"
Explanation:
At i=0 ("b"): First non-repeating character is 'b'.
At i=1 ("bb"): No non-repeating character, so '#'.
Table of Content
[Naive Approach] Nested Loop - O(n ^ 2) time and O(n) space
The idea is to use a frequency array to count character occurrences and scan the processed part of the string to find the first non-repeating character.
- Update the frequency of the current character.
- Scan from the beginning and append the first character with frequency 1; if none exists, append '#'.
- Repeat for each character and return the result.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
string firstNonRepeating(string &s)
{
string ans;
int n = s.size();
// frequency vector for all ASCII characters
vector<int> freq(26, 0);
// Process each character in the stream
for (int i = 0; i < n; i++)
{
// Update frequency for the current character
freq[s[i] - 'a']++;
// Scan from the beginning to find the first non-repeating character
bool found = false;
for (int j = 0; j <= i; j++)
{
if (freq[s[j] - 'a'] == 1)
{
ans.push_back(s[j]);
found = true;
break;
}
}
if (!found)
{
ans.push_back('#');
}
}
return ans;
}
int main()
{
string s = "aabc";
string ans = firstNonRepeating(s);
cout << ans << endl;
return 0;
}
class GFG {
static String firstNonRepeating(String s)
{
StringBuilder ans = new StringBuilder();
int n = s.length();
// frequency array for all ASCII characters
int[] freq = new int[26];
// Process each character in the stream
for (int i = 0; i < n; i++) {
// Update frequency for the current character
freq[s.charAt(i) - 'a']++;
// Scan from the beginning to find the
// first non-repeating character
boolean found = false;
for (int j = 0; j <= i; j++) {
if (freq[s.charAt(j) - 'a'] == 1) {
ans.append(s.charAt(j));
found = true;
break;
}
}
if (!found) {
ans.append('#');
}
}
return ans.toString();
}
public static void main(String[] args)
{
String s = "aabc";
String ans = firstNonRepeating(s);
System.out.println(ans);
}
}
def firstNonRepeating(s):
ans = ''
n = len(s)
# frequency list for all ASCII characters
freq = [0] * 26
# Process each character in the stream
for i in range(n):
# Update frequency for the current character
freq[ord(s[i]) - ord('a')] += 1
# Scan from the beginning to find the
# first non-repeating character
found = False
for j in range(i + 1):
if freq[ord(s[j]) - ord('a')] == 1:
ans += s[j]
found = True
break
if not found:
ans += '#'
return ans
if __name__ == "__main__":
s = "aabc"
ans = firstNonRepeating(s)
print(ans)
using System;
using System.Text;
class GFG {
static string firstNonRepeating(string s)
{
StringBuilder ans = new StringBuilder();
int n = s.Length;
// frequency array for all ASCII characters
int[] freq = new int[26];
// Process each character in the stream
for (int i = 0; i < n; i++) {
// Update frequency for the current character
freq[s[i] - 'a']++;
// Scan from the beginning to find the first
// non-repeating character
bool found = false;
for (int j = 0; j <= i; j++) {
if (freq[s[j] - 'a'] == 1) {
ans.Append(s[j]);
found = true;
break;
}
}
if (!found) {
ans.Append('#');
}
}
return ans.ToString();
}
public static void Main()
{
string s = "aabc";
string ans = firstNonRepeating(s);
Console.WriteLine(ans);
}
}
function firstNonRepeating(s)
{
let ans = "";
let n = s.length;
// frequency array for all ASCII characters
let freq = new Array(26).fill(0);
// Process each character in the stream
for (let i = 0; i < n; i++) {
// Update frequency for the current character
freq[s.charCodeAt(i) - "a".charCodeAt(0)]++;
// Scan from the beginning to find the first
// non-repeating character
let found = false;
for (let j = 0; j <= i; j++) {
if (freq[s.charCodeAt(j) - "a".charCodeAt(0)]
=== 1) {
ans += s[j];
found = true;
break;
}
}
if (!found) {
ans += "#";
}
}
return ans;
}
// Driver Code
let s = "aabc";
let ans = firstNonRepeating(s);
console.log(ans);
Output
a#bb
[Better Approach] Queue and Frequency Array - O(n) Time and O(n) Space
The idea is to use a frequency array to track character occurrences and a queue to maintain characters in their order of appearance.
- For each character, update its frequency and remove repeating characters from the front of the queue.
- If the queue is not empty, append its front character to the result; otherwise, append '#'.
- Return the result after processing all characters.
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
string firstNonRepeating(string &s)
{
string ans = "";
vector<int> count(26, 0);
queue<char> q;
for (int i = 0; i < s.length(); i++)
{
// if non-repeating element found push it in queue
if (count[s[i] - 'a'] == 0)
{
q.push(s[i]);
}
count[s[i] - 'a']++;
// if front element is repeating pop it from the queue
while (!q.empty() && count[q.front() - 'a'] > 1)
{
q.pop();
}
// if queue is not empty append front
// element else append "#" in ans string.
if (!q.empty())
{
ans += q.front();
}
else
{
ans += '#';
}
}
return ans;
}
int main()
{
string s = "aabc";
string ans = firstNonRepeating(s);
cout << ans << "\n";
return 0;
}
import java.util.LinkedList;
import java.util.Queue;
class GFG {
static String firstNonRepeating(String s)
{
StringBuilder ans = new StringBuilder();
int[] count = new int[26];
Queue<Character> q = new LinkedList<>();
for (int i = 0; i < s.length(); i++) {
// if non-repeating element found push it in
// queue
if (count[s.charAt(i) - 'a'] == 0) {
q.add(s.charAt(i));
}
count[s.charAt(i) - 'a']++;
// if front element is repeating pop it from the
// queue
while (!q.isEmpty()
&& count[q.peek() - 'a'] > 1) {
q.poll();
}
// if queue is not empty append front
// element else append "#" in ans string.
if (!q.isEmpty()) {
ans.append(q.peek());
}
else {
ans.append('#');
}
}
return ans.toString();
}
public static void main(String[] args)
{
String s = "aabc";
String ans = firstNonRepeating(s);
System.out.println(ans);
}
}
from collections import deque
def firstNonRepeating(s):
ans = ""
count = [0] * 26
q = deque()
for char in s:
# if non-repeating element found push it in queue
if count[ord(char) - ord('a')] == 0:
q.append(char)
count[ord(char) - ord('a')] += 1
# if front element is repeating pop it from the queue
while q and count[ord(q[0]) - ord('a')] > 1:
q.popleft()
# if queue is not empty append front
# element else append "#" in ans string.
if q:
ans += q[0]
else:
ans += '#'
return ans
if __name__ == '__main__':
s = "aabc"
ans = firstNonRepeating(s)
print(ans)
using System;
using System.Collections.Generic;
using System.Text;
class GFG {
string firstNonRepeating(string s)
{
StringBuilder ans = new StringBuilder();
int[] count = new int[26];
Queue<char> q = new Queue<char>();
for (int i = 0; i < s.Length; i++) {
if (count[s[i] - 'a'] == 0)
q.Enqueue(s[i]);
count[s[i] - 'a']++;
while (q.Count > 0 && count[q.Peek() - 'a'] > 1)
q.Dequeue();
if (q.Count > 0)
ans.Append(q.Peek());
else
ans.Append('#');
}
return ans.ToString();
}
public static void Main()
{
string s = "aabc";
GFG obj = new GFG();
Console.WriteLine(obj.firstNonRepeating(s));
}
}
// Node class for doubly linked list
class Node {
constructor(data)
{
this.data = data;
this.prev = null;
this.next = null;
}
}
// Queue implemented using doubly linked list
class Queue {
constructor()
{
this.front = null;
this.rear = null;
this.size = 0;
}
// Add element at the rear
enqueue(x)
{
let node = new Node(x);
if (!this.rear) {
this.front = this.rear = node;
}
else {
node.prev = this.rear;
this.rear.next = node;
this.rear = node;
}
this.size++;
}
// Remove element from the front
dequeue()
{
if (!this.front) {
console.log("Queue is empty");
return null;
}
let val = this.front.data;
this.front = this.front.next;
if (this.front)
this.front.prev = null;
else
this.rear = null;
this.size--;
return val;
}
// Get front element without removing
frontElement()
{
return this.front ? this.front.data : null;
}
isEmpty() { return this.size === 0; }
}
// Function to find first non-repeating character in a
// stream
function firstNonRepeating(s)
{
let ans = "";
let count = new Array(26).fill(0);
let q = new Queue();
for (let i = 0; i < s.length; i++) {
let idx = s.charCodeAt(i) - "a".charCodeAt(0);
// if first occurrence, enqueue it
if (count[idx] === 0) {
q.enqueue(s[i]);
}
count[idx]++;
// remove repeating elements from front
while (!q.isEmpty()
&& count[q.frontElement().charCodeAt(0)
- "a".charCodeAt(0)]
> 1) {
q.dequeue();
}
// append first non-repeating or '#' if none
ans += q.isEmpty() ? "#" : q.frontElement();
}
return ans;
}
// Driver code
let s = "aabc";
let ans = firstNonRepeating(s);
console.log(ans);
Output
a#bb
[Expected Approach] Frequency and First Occurrence Arrays – O(26 * n) Time and O(1) Space
The idea is to maintain a frequency array to count character occurrences and another array to store the first position of each character.
- While traversing the string, we update the frequency of each character and find the character with frequency 1 that appeared earliest.
- If no such character exists, we append '#' to the result.
#include <iostream>
#include <vector>
using namespace std;
string firstNonRepeating(string &s)
{
int n = s.size();
vector<int> freq(26, 0);
vector<int> firstPos(26, -1);
// record first occurrence for each character
for (int i = 0; i < n; i++)
{
if (firstPos[s[i] - 'a'] == -1)
firstPos[s[i] - 'a'] = i;
}
string result = "";
for (int i = 0; i < n; i++)
{
freq[s[i] - 'a']++;
char chosen = '#';
int earliest = n + 1;
// find earliest character with frequency 1
for (int j = 0; j < 26; j++)
{
if (freq[j] == 1 && earliest > firstPos[j])
{
chosen = char(j + 'a');
earliest = firstPos[j];
}
}
result += chosen;
}
return result;
}
int main()
{
string s = "aabc";
cout << firstNonRepeating(s) << endl;
return 0;
}
class GFG {
static String firstNonRepeating(String s)
{
int n = s.length();
int[] freq = new int[26];
int[] firstPos = new int[26];
for (int i = 0; i < 26; i++)
firstPos[i] = -1;
// record first occurrence for each character
for (int i = 0; i < n; i++) {
int idx = s.charAt(i) - 'a';
if (firstPos[idx] == -1)
firstPos[idx] = i;
}
StringBuilder result = new StringBuilder();
for (int i = 0; i < n; i++) {
int idx = s.charAt(i) - 'a';
freq[idx]++;
char chosen = '#';
int earliest = n + 1;
// find earliest character with frequency 1
for (int j = 0; j < 26; j++) {
if (freq[j] == 1
&& firstPos[j] < earliest) {
chosen = (char)(j + 'a');
earliest = firstPos[j];
}
}
result.append(chosen);
}
return result.toString();
}
public static void main(String[] args)
{
String s = "aabc";
System.out.println(firstNonRepeating(s));
}
}
def firstNonRepeating(s):
n = len(s)
freq = [0] * 26
firstPos = [-1] * 26
# record first occurrence for each character
for i in range(n):
if firstPos[ord(s[i]) - ord('a')] == -1:
firstPos[ord(s[i]) - ord('a')] = i
result = ""
for i in range(n):
freq[ord(s[i]) - ord('a')] += 1
chosen = '#'
earliest = n + 1
# find earliest character with frequency 1
for j in range(26):
if freq[j] == 1 and earliest > firstPos[j]:
chosen = chr(j + ord('a'))
earliest = firstPos[j]
result += chosen
return result
if __name__ == '__main__':
s = "aabc"
print(firstNonRepeating(s))
using System;
using System.Text;
class GfG {
static string firstNonRepeating(string s)
{
int n = s.Length;
int[] freq = new int[26];
int[] firstPos = new int[26];
Array.Fill(firstPos, -1);
// record first occurrence for each character
for (int i = 0; i < n; i++) {
if (firstPos[s[i] - 'a'] == -1)
firstPos[s[i] - 'a'] = i;
}
StringBuilder result = new StringBuilder();
for (int i = 0; i < n; i++) {
freq[s[i] - 'a']++;
char chosen = '#';
int earliest = n + 1;
// find earliest character with frequency 1
for (int j = 0; j < 26; j++) {
if (freq[j] == 1
&& earliest > firstPos[j]) {
chosen = (char)(j + 'a');
earliest = firstPos[j];
}
}
result.Append(chosen);
}
return result.ToString();
}
public static void Main()
{
string s = "aabc";
Console.WriteLine(firstNonRepeating(s));
}
}
function firstNonRepeating(s)
{
let n = s.length;
let freq = new Array(26).fill(0);
let firstPos = new Array(26).fill(-1);
// record first occurrence for each character
for (let i = 0; i < n; i++) {
if (firstPos[s.charCodeAt(i) - "a".charCodeAt(0)]
=== -1)
firstPos[s.charCodeAt(i) - "a".charCodeAt(0)]
= i;
}
let result = "";
for (let i = 0; i < n; i++) {
freq[s.charCodeAt(i) - "a".charCodeAt(0)]++;
let chosen = "#";
let earliest = n + 1;
// find earliest character with frequency 1
for (let j = 0; j < 26; j++) {
if (freq[j] === 1 && earliest > firstPos[j]) {
chosen = String.fromCharCode(
j + "a".charCodeAt(0));
earliest = firstPos[j];
}
}
result += chosen;
}
return result;
}
// Driver Code
let s = "aabc";
console.log(firstNonRepeating(s));
Output
a#bb