Longest Substring Without Repeating Characters
Last Updated :
20 Mar, 2025
Given a string s having lowercase characters, find the length of the longest substring without repeating characters.
Examples:
Input: s = "geeksforgeeks"
Output: 7
Explanation: The longest substrings without repeating characters are "eksforg” and "ksforge", with lengths of 7.
Input: s = "aaa"
Output: 1
Explanation: The longest substring without repeating characters is "a"
Input: s = "abcdefabcbb"
Output: 6
Explanation: The longest substring without repeating characters is "abcdef".
[Naive Approach] Substrings Starting From Every Index - O(26*n) Time and O(1) Space
The idea is to find length of longest substring with distinct characters starting from every index and maximum of all such lengths will be our answer.
To find the length of the longest substring with distinct characters starting from an index, we create a new visited array of size = 26 to keep track of included characters in the substring. vis[0] checks for 'a', vis[1] checks for 'b', vis[2] checks for 'c' and so on.
Note: The array size is fixed at 26, representing the lowercase English alphabet as a constant
C++
#include <bits/stdc++.h>
using namespace std;
int longestUniqueSubstr(string &s)
{
int n = s.size();
int res = 0;
for (int i = 0; i < n; i++)
{
// Initializing all characters as not visited
vector<bool> vis(26, false);
for (int j = i; j < n; j++)
{
// If current character is visited
// Break the loop
if (vis[s[j] - 'a'] == true)
break;
// Else update the result if this window is larger,
// and mark current character as visited.
else
{
res = max(res, j - i + 1);
vis[s[j] - 'a'] = true;
}
}
}
return res;
}
int main()
{
string s = "geeksforgeeks";
cout << longestUniqueSubstr(s);
return 0;
}
Java
// Java program to find the length of the longest
// substring without repeating characters
import java.util.*;
class GfG {
static int longestUniqueSubstr(String s)
{
int n = s.length();
int res = 0;
for (int i = 0; i < n; i++) {
// Initializing all characters as not visited
boolean[] vis = new boolean[26];
for (int j = i; j < n; j++) {
// If current character is visited
// Break the loop
if (vis[s.charAt(j) - 'a'] == true)
break;
// Else update the result if this window is
// larger, and mark current character as
// visited.
else {
res = Math.max(res, j - i + 1);
vis[s.charAt(j) - 'a'] = true;
}
}
}
return res;
}
public static void main(String[] args)
{
String s = "geeksforgeeks";
System.out.println(longestUniqueSubstr(s));
}
}
Python
def longestUniqueSubstr(s):
n = len(s)
res = 0
for i in range(n):
# Initializing all characters as not visited
vis = [False] * 26
for j in range(i, n):
# If current character is visited
# Break the loop
if vis[ord(s[j]) - ord('a')] == True:
break
# Else update the result if this window is larger,
# and mark current character as visited.
else:
res = max(res, j - i + 1)
vis[ord(s[j]) - ord('a')] = True
return res
if __name__ == "__main__":
s = "geeksforgeeks"
print(longestUniqueSubstr(s))
C#
// C# program to find the length of the longest
// substring without repeating characters
using System;
class GfG {
static int longestUniqueSubstr(string s) {
int n = s.Length;
int res = 0;
for (int i = 0; i < n; i++) {
// Initializing all characters as not visited
bool[] vis = new bool[26];
for (int j = i; j < n; j++) {
// If current character is visited
// Break the loop
if (vis[s[j] - 'a'] == true)
break;
// Else update the result if this window is larger,
// and mark current character as visited.
else {
res = Math.Max(res, j - i + 1);
vis[s[j] - 'a'] = true;
}
}
}
return res;
}
static void Main() {
string s = "geeksforgeeks";
Console.WriteLine(longestUniqueSubstr(s));
}
}
JavaScript
function longestUniqueSubstr(s) {
let n = s.length;
let res = 0;
for (let i = 0; i < n; i++) {
// Initializing all characters as not visited
let vis = new Array(26).fill(false);
for (let j = i; j < n; j++) {
// If current character is visited
// Break the loop
if (vis[s.charCodeAt(j) - 'a'.charCodeAt(0)] === true)
break;
// Else update the result if this window is larger,
// and mark current character as visited.
else {
res = Math.max(res, j - i + 1);
vis[s.charCodeAt(j) - 'a'.charCodeAt(0)] = true;
}
}
}
return res;
}
// Driver Code
let s = "geeksforgeeks";
console.log(longestUniqueSubstr(s));
Time Complexity: O(n*26), the outer loop runs O(n) time, and the inner loop runs in O(26) in the worst case (considering all unique characters), resulting in a total time complexity of O(n*26).
Auxiliary Space: O(1), vis array has size 26 which is constant.
[Expected Approach 1] Using Sliding Window - O(n) Time and O(1) Space
The idea is to maintain a window of distinct characters. The window is initialized as single character. We keep extending the window on the right side till we see distinct characters. When we see a repeating character, we remove characters from the left side of the window. We keep track of the maximum length window.
Below are the detailed steps:
- Initialize two pointers left and right with 0, which define the current window being considered.
- The
right
pointer moves from left to right, extending the current window. - If the character at right pointer is not visited, it's marked as visited.
- If the character at right pointer is visited, it means there is a repeating character. The left pointer moves to the right while marking visited characters as false until the repeating character is no longer part of the current window.
- The length of the current window (right - left + 1) is calculated and answer is updated accordingly.
Working:
C++
#include <bits/stdc++.h>
using namespace std;
int longestUniqueSubstr(string& s) {
if (s.length() == 0 || s.length() == 1)
return s.length();
int res = 0;
vector<bool>vis(26, false);
// left and right pointer of sliding window
int left = 0, right = 0;
while (right < s.length()) {
// If character is repeated, move left pointer marking
// visited characters as false until the repeating
// character is no longer part of the current window
while (vis[s[right] - 'a'] == true) {
vis[s[left] - 'a'] = false;
left++;
}
vis[s[right] - 'a'] = true;
// The length of the current window (right - left + 1)
// is calculated and answer is updated accordingly.
res = max(res, (right - left + 1));
right++;
}
return res;
}
int main() {
string s = "geeksforgeeks";
cout << longestUniqueSubstr(s);
return 0;
}
Java
// Java code to find the largest substring with non-repeating
// characters using Sliding Window
class GfG {
static int longestUniqueSubstr(String s) {
if (s.length() == 0 || s.length() == 1)
return s.length();
int res = 0;
boolean[] vis = new boolean[26];
// left and right pointer of sliding window
int left = 0, right = 0;
while (right < s.length()) {
// If character is repeated, move left pointer marking
// visited characters as false until the repeating
// character is no longer part of the current window
while (vis[s.charAt(right) - 'a'] == true) {
vis[s.charAt(left) - 'a'] = false;
left++;
}
vis[s.charAt(right) - 'a'] = true;
// The length of the current window (right - left + 1)
// is calculated and answer is updated accordingly.
res = Math.max(res, (right - left + 1));
right++;
}
return res;
}
public static void main(String[] args) {
String s = "geeksforgeeks";
System.out.println(longestUniqueSubstr(s));
}
}
Python
# Python code to find the largest substring with non-repeating
# characters using Sliding Window
MAX_CHAR = 26
def longestUniqueSubstr(s):
if len(s) == 0 or len(s) == 1:
return len(s)
res = 0
vis = [False] * 26
# left and right pointer of sliding window
left = 0
right = 0
while right < len(s):
# If character is repeated, move left pointer marking
# visited characters as false until the repeating
# character is no longer part of the current window
while vis[ord(s[right]) - ord('a')] == True:
vis[ord(s[left]) - ord('a')] = False
left += 1
vis[ord(s[right]) - ord('a')] = True
# The length of the current window (right - left + 1)
# is calculated and answer is updated accordingly.
res = max(res, (right - left + 1))
right += 1
return res
if __name__ == "__main__":
s = "geeksforgeeks"
print(longestUniqueSubstr(s))
C#
using System;
class GfG {
static int longestUniqueSubstr(string s) {
if (s.Length == 0 || s.Length == 1)
return s.Length;
int res = 0;
bool[] vis = new bool[26];
// left and right pointer of sliding window
int left = 0, right = 0;
while (right < s.Length) {
while (vis[s[right] - 'a'] == true) {
vis[s[left] - 'a'] = false;
left++;
}
vis[s[right] - 'a'] = true;
// The length of the current window (right - left + 1)
// is calculated and answer is updated accordingly.
res = Math.Max(res, (right - left + 1));
right++;
}
return res;
}
static void Main() {
string s = "geeksforgeeks";
Console.WriteLine(longestUniqueSubstr(s));
}
}
JavaScript
function longestUniqueSubstr(s) {
if (s.length === 0 || s.length === 1)
return s.length;
let res = 0;
let vis = new Array(26).fill(false);
// left and right pointer of sliding window
let left = 0, right = 0;
while (right < s.length) {
while (vis[s[right].charCodeAt(0) - 'a'.charCodeAt(0)] === true) {
vis[s[left].charCodeAt(0) - 'a'.charCodeAt(0)] = false;
left++;
}
vis[s[right].charCodeAt(0) - 'a'.charCodeAt(0)] = true;
res = Math.max(res, (right - left + 1));
right++;
}
return res;
}
// Driver Code
const s = "geeksforgeeks";
console.log(longestUniqueSubstr(s));
[Expected Approach 2] Using Last Index of Each Character - O(n) Time and O(1) Space
The approach stores the last indexes of already visited characters. The idea is to maintain a window of distinct characters. Start from the first character, and keep extending the window on the right side till we see distinct characters. When we see a repeating character, we check for the last index of the repeated character:
- If last index of repeated character >= starting index of the current window, then we update the starting index of the current window to last index of repeated character + 1 to remove the repeated character.
- If last index of repeated character < starting index of the current window, then it means that the repeated character is already outside the current window so the window size remains unchanged.
After iterating over all the characters, the largest window size will be our answer.
Working:
C++
#include <bits/stdc++.h>
using namespace std;
int longestUniqueSubstr(string &s) {
int n = s.size();
int res = 0;
vector<int> lastIndex(26, -1);
// Initialize start of current window
int start = 0;
// Move end of current window
for (int end = 0; end < n; end++) {
start = max(start, lastIndex[s[end] - 'a'] + 1);
// Update result if we get a larger window
res = max(res, end - start + 1);
// Update last index of s[end]
lastIndex[s[end] - 'a'] = end;
}
return res;
}
int main() {
string s = "geeksforgeeks";
cout << longestUniqueSubstr(s);
return 0;
}
Java
class GfG {
static int longestUniqueSubstr(String s) {
int n = s.length();
int res = 0;
// last index of all characters is initialized as -1
int[] lastIndex = new int[26];
for (int i = 0; i < 26; i++) {
lastIndex[i] = -1;
}
// Initialize start of current window
int start = 0;
// Move end of current window
for (int end = 0; end < n; end++) {
// Find the last index of s[end]
// Update starting index of current window as
// maximum of current value of end and last index + 1
start = Math.max(start, lastIndex[s.charAt(end) - 'a'] + 1);
// Update result if we get a larger window
res = Math.max(res, end - start + 1);
// Update last index of s[end]
lastIndex[s.charAt(end) - 'a'] = end;
}
return res;
}
public static void main(String[] args) {
String s = "geeksforgeeks";
System.out.println(longestUniqueSubstr(s));
}
}
Python
# Python code to find the largest substring with non-repeating
# characters using last index of repeated character
def longestUniqueSubstr(s):
n = len(s)
res = 0
lastIndex = [-1] * 26
# Initialize start of current window
start = 0
# Move end of current window
for end in range(n):
start = max(start, lastIndex[ord(s[end]) - ord('a')] + 1)
# Update result if we get a larger window
res = max(res, end - start + 1)
# Update last index of s[end]
lastIndex[ord(s[end]) - ord('a')] = end
return res
if __name__ == "__main__":
s = "geeksforgeeks"
print(longestUniqueSubstr(s))
C#
// C# code to find the largest substring with non-repeating
// characters using last index of repeated character
using System;
class GfG {
const int MAX_CHAR = 26;
public static int longestUniqueSubstr(string s) {
int n = s.Length;
int res = 0;
// last index of all characters is initialized as -1
int[] lastIndex = new int[MAX_CHAR];
for (int i = 0; i < MAX_CHAR; i++) {
lastIndex[i] = -1;
}
// Initialize start of current window
int start = 0;
// Move end of current window
for (int end = 0; end < n; end++) {
start = Math.Max(start, lastIndex[s[end] - 'a'] + 1);
// Update result if we get a larger window
res = Math.Max(res, end - start + 1);
// Update last index of s[end]
lastIndex[s[end] - 'a'] = end;
}
return res;
}
static void Main() {
string s = "geeksforgeeks";
Console.WriteLine(longestUniqueSubstr(s));
}
}
JavaScript
function longestUniqueSubstr(s) {
const n = s.length;
let res = 0;
// last index of all characters is initialized as -1
const lastIndex = new Array(26).fill(-1);
// Initialize start of current window
let start = 0;
// Move end of current window
for (let end = 0; end < n; end++) {
start = Math.max(start, lastIndex[s.charCodeAt(end) - 'a'.charCodeAt(0)] + 1);
// Update result if we get a larger window
res = Math.max(res, end - start + 1);
// Update last index of s[end]
lastIndex[s.charCodeAt(end) - 'a'.charCodeAt(0)] = end;
}
return res;
}
// Driver Code
const s = "geeksforgeeks";
console.log(longestUniqueSubstr(s));
Longest Substring With Distinct Character
Longest substring without repeating characters
Similar Reads
Basics & Prerequisites
Data Structures
Array Data StructureIn this article, we introduce array, implementation in different popular languages, its basic operations and commonly seen problems / interview questions. An array stores items (in case of C/C++ and Java Primitive Arrays) or their references (in case of Python, JS, Java Non-Primitive) at contiguous
3 min read
String in Data StructureA string is a sequence of characters. The following facts make string an interesting data structure.Small set of elements. Unlike normal array, strings typically have smaller set of items. For example, lowercase English alphabet has only 26 characters. ASCII has only 256 characters.Strings are immut
2 min read
Hashing in Data StructureHashing is a technique used in data structures that efficiently stores and retrieves data in a way that allows for quick access. Hashing involves mapping data to a specific index in a hash table (an array of items) using a hash function. It enables fast retrieval of information based on its key. The
2 min read
Linked List Data StructureA linked list is a fundamental data structure in computer science. It mainly allows efficient insertion and deletion operations compared to arrays. Like arrays, it is also used to implement other data structures like stack, queue and deque. Hereâs the comparison of Linked List vs Arrays Linked List:
2 min read
Stack Data StructureA Stack is a linear data structure that follows a particular order in which the operations are performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). LIFO implies that the element that is inserted last, comes out first and FILO implies that the element that is inserted first
2 min read
Queue Data StructureA Queue Data Structure is a fundamental concept in computer science used for storing and managing data in a specific order. It follows the principle of "First in, First out" (FIFO), where the first element added to the queue is the first one to be removed. It is used as a buffer in computer systems
2 min read
Tree Data StructureTree Data Structure is a non-linear data structure in which a collection of elements known as nodes are connected to each other via edges such that there exists exactly one path between any two nodes. Types of TreeBinary Tree : Every node has at most two childrenTernary Tree : Every node has at most
4 min read
Graph Data StructureGraph Data Structure is a collection of nodes connected by edges. It's used to represent relationships between different entities. If you are looking for topic-wise list of problems on different topics like DFS, BFS, Topological Sort, Shortest Path, etc., please refer to Graph Algorithms. Basics of
3 min read
Trie Data StructureThe Trie data structure is a tree-like structure used for storing a dynamic set of strings. It allows for efficient retrieval and storage of keys, making it highly effective in handling large datasets. Trie supports operations such as insertion, search, deletion of keys, and prefix searches. In this
15+ min read
Algorithms
Searching AlgorithmsSearching algorithms are essential tools in computer science used to locate specific items within a collection of data. In this tutorial, we are mainly going to focus upon searching in an array. When we search an item in an array, there are two most common algorithms used based on the type of input
2 min read
Sorting AlgorithmsA Sorting Algorithm is used to rearrange a given array or list of elements in an order. For example, a given array [10, 20, 5, 2] becomes [2, 5, 10, 20] after sorting in increasing order and becomes [20, 10, 5, 2] after sorting in decreasing order. There exist different sorting algorithms for differ
3 min read
Introduction to RecursionThe process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. A recursive algorithm takes one step toward solution and then recursively call itself to further move. The algorithm stops once we reach the solution
14 min read
Greedy AlgorithmsGreedy algorithms are a class of algorithms that make locally optimal choices at each step with the hope of finding a global optimum solution. At every step of the algorithm, we make a choice that looks the best at the moment. To make the choice, we sometimes sort the array so that we can always get
3 min read
Graph AlgorithmsGraph is a non-linear data structure like tree data structure. The limitation of tree is, it can only represent hierarchical data. For situations where nodes or vertices are randomly connected with each other other, we use Graph. Example situations where we use graph data structure are, a social net
3 min read
Dynamic Programming or DPDynamic Programming is an algorithmic technique with the following properties.It is mainly an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of
3 min read
Bitwise AlgorithmsBitwise algorithms in Data Structures and Algorithms (DSA) involve manipulating individual bits of binary representations of numbers to perform operations efficiently. These algorithms utilize bitwise operators like AND, OR, XOR, NOT, Left Shift, and Right Shift.BasicsIntroduction to Bitwise Algorit
4 min read
Advanced
Segment TreeSegment Tree is a data structure that allows efficient querying and updating of intervals or segments of an array. It is particularly useful for problems involving range queries, such as finding the sum, minimum, maximum, or any other operation over a specific range of elements in an array. The tree
3 min read
Pattern SearchingPattern searching algorithms are essential tools in computer science and data processing. These algorithms are designed to efficiently find a particular pattern within a larger set of data. Patten SearchingImportant Pattern Searching Algorithms:Naive String Matching : A Simple Algorithm that works i
2 min read
GeometryGeometry is a branch of mathematics that studies the properties, measurements, and relationships of points, lines, angles, surfaces, and solids. From basic lines and angles to complex structures, it helps us understand the world around us.Geometry for Students and BeginnersThis section covers key br
2 min read
Interview Preparation
Practice Problem