October 01, 2020
Hey happy folks 👋! It’s a brand new day and it’s time to look at another problem from LeetCode - Longest Substring Without Repeating Characters.
0003 - Longest Substring Without Repeating Characters.
Given a string s
, find the length of the longest substring without repeating characters.
s
consists of English letters, digits, symbols and spaces.Input: s = "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.
Input: s = "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.
Input: s = "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3.
Notice that the answer must be a substring, "pwke" is a subsequence and not a substring.
The input will be a string containing characters which may or may not be repeated. The ask is to find the longest substring (a part of the given string) having all distinct characters.
One characteristic of a substring is that all the characters are contiguous. For e.g, in a given string
s = redquark
, the valid substrings are - edq
, ar
, red
, quar
etc. The substrings rd
, qur
are not valid substrings because even though they contain characters from the source strings, those characters are not continuous.
Apart from above, we are given constraints on the size of string and the characters that are present in a string.
There can be many substrings as outputs but we have to return only the longest among them.
Prerequisite: Sliding Window Algorithm.
From the input, we can gather the following information -
Are you thinking what I am thinking 🤔? Yes, this is a classic example of a problem that can be solved using the legendary technique - Sliding Window Algorithm.
Following are the steps that we will follow -
start
and ending index end
of the current window. Both will be 0
at the beginning.Set
that will store all the unique characters that we have encountered. maxLength
that will keep track of the length of the longest valid substring.Set
the we will add it and increment the end
index. The maxLength
will be the maximum of Set.size()
and existing maxLength
.Set
, we will increment the start
and we will remove the character at start
index of the string.maxLength
.We are scanning the string from left to right only once, hence the time complexity will be O(n).
We are using Set
as a data structure to facilitate our computation, therefore, the space complexity should also be O(n), right? Wrong!
WHY?
The problem clearly states that the string contains only English letters, digits, symbols and spaces and are covered in 256 code points. Therefore, a string will be made up of a combination of these characters.
Since a Set
can contain only unique elements, at any point the size of Set
cannot be more than 256.
What does this mean? This means that the size of set is a function independent of the size of the input. It is a constant. Therefore, the space complexity will be O(1) (let me know in comments if you think otherwise).
After analyzing and deciding on the approach, it’s time to write some code -
package org.redquark.tutorials.leetcode;
import java.util.HashSet;
import java.util.Set;
public class LongestSubstringWithoutRepeatingCharacters {
public int lengthOfLongestSubstring(String s) {
// Base condition
if (s == null || s.equals("")) {
return 0;
}
// Starting window index
int start = 0;
// Ending window index
int end = 0;
// Maximum length of substring
int maxLength = 0;
// This set will store the unique characters
Set<Character> uniqueCharacters = new HashSet<>();
// Loop for each character in the string
while (end < s.length()) {
if (uniqueCharacters.add(s.charAt(end))) {
end++;
maxLength = Math.max(maxLength, uniqueCharacters.size());
} else {
uniqueCharacters.remove(s.charAt(start));
start++;
}
}
return maxLength;
}
}
def lengthOfLongestSubstring(s: str) -> int:
# Base condition
if s == "":
return 0
# Starting index of window
start = 0
# Ending index of window
end = 0
# Maximum length of substring without repeating characters
maxLength = 0
# Set to store unique characters
unique_characters = set()
# Loop for each character in the string
while end < len(s):
if s[end] not in unique_characters:
unique_characters.add(s[end])
end += 1
maxLength = max(maxLength, len(unique_characters))
else:
unique_characters.remove(s[start])
start += 1
return maxLength
var lengthOfLongestSubstring = function (s) {
// Base condition
if (!s) {
return 0;
}
// Starting index of the window
let start = 0;
// Ending index of the window
let end = 0;
// Maximum length of the substring
let maxLength = 0;
// Set to store the unique characters
const uniqueCharacters = new Set();
// Loop for each character in the string
while (end < s.length) {
if (!uniqueCharacters.has(s[end])) {
uniqueCharacters.add(s[end]);
end++;
maxLength = Math.max(maxLength, uniqueCharacters.size);
} else {
uniqueCharacters.delete(s[start]);
start++;
}
}
return maxLength;
};
fun lengthOfLongestSubstring(s: String): Int {
// Base condition
if (s == "") {
return 0
}
// Starting window index
var start = 0
// Ending window index
var end = 0
// Maximum length of substring
var maxLength = 0
// This set will store the unique characters
val uniqueCharacters: MutableSet<Char> = HashSet()
// Loop for each character in the string
while (end < s.length) {
if (uniqueCharacters.add(s[end])) {
end++
maxLength = maxLength.coerceAtLeast(uniqueCharacters.size)
} else {
uniqueCharacters.remove(s[start])
start++
}
}
return maxLength
}
That’s all folks! In this post, we solved LeetCode problem #3 using Sliding Window Technique.
I hope you have enjoyed this post. Feel free to share your thoughts on this.
You can find the complete source code on my GitHub repository. If you like what you learn. feel free to fork 🔪 and star ⭐ it.
Till next time… Happy coding 😄 and Namaste 🙏!