First Non Repeating Character

Last Updated : 21 Feb, 2026

Given a string s consisting of lowercase letters, for each position 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#bc
Explanation:
After 'a' → first unique = 'a'
After 'aa' → no unique → '#'
After 'aab' → first unique = 'b'
After 'aabc' → first unique = 'c'
Result = a#bc

Input: s = "bb"
Output: b#
Explanation:
After 'b' → first unique = 'b'
After 'bb'→ no unique → '#'
Result = b#

Try it on GfG Practice
redirect icon

[Naive Approach] Using Nested Loop - O(n2) time and O(n) space

This approach maintains a frequency count of each character using a vector. For each character in the string, it scans from the beginning to find the first non-repeating character by checking the frequency of each character up to that point. If a non-repeating character is found, it is appended to the result; otherwise, # is appended when no such character exists. This process ensures that the first non-repeating character is identified at each step.

C++
#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;
}
Java
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);
    }
}
Python
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)
C#
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);
    }
}
JavaScript
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] Using Queue and Frequency Array - O(n) Time and O(n) Space

We use a count array of size 26 to track character frequencies and a queue to maintain their order of appearance. For each new character, we update its frequency and push it into the queue. Then, we remove characters from the front of the queue until the first non-repeating character is found, or the queue becomes empty.

C++
#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;
}
Java
import java.util.Queue;
import java.util.LinkedList;

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);
    }
}
Python
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)
C#
using System;
using System.Collections.Generic;

class GfG {
    static string firstNonRepeating(string s) {
        string ans = "";
        int[] count = new int[26];
        Queue<char> q = new Queue<char>();

        foreach (char c in s) {
            
            // if non-repeating element found push it in queue
            if (count[c - 'a'] == 0) {
                q.Enqueue(c);
            }
            count[c - 'a']++;

            // if front element is repeating pop it from the queue
            while (q.Count > 0 && count[q.Peek() - 'a'] > 1) {
                q.Dequeue();
            }

            // if queue is not empty append front
            // element else append "#" in ans string.
            if (q.Count > 0) {
                ans += q.Peek();
            } else {
                ans += '#';
            }
        }

        return ans;
    }

    static void Main() {
        string s = "aabc";
        string ans = firstNonRepeating(s);
        Console.WriteLine(ans);
    }
}
JavaScript
// 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] Using Frequency and Last Occurrence Array- O(n) Time and O(1) Space

We maintain a frequency array to count occurrences and another array to store the first position of each character. While processing the string, we update frequencies and then check which character has frequency 1 and appeared earliest. That character becomes the current answer; if none exists, we place a '#'.

C++
#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;
}
Java
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));
    }
}
Python
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))
C#
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));
    }
}
JavaScript
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
Comment