Problem Statement
This problem is from Leetcode – Longest substring without repeating characters. The problem statement is as below:
Given a string s, find the length of the longest substring
without repeating characters.
Solution
Approach – 1
- Initialize a string curStr to empty string. This is where we’ll store the sub-strings as we move forward.
- Initialize the re-start index to zero. We’ll use this to move our sub-string window to the right.
- Iterate through the given string in a for loop.
- If the current char is not part of curStr, then append to it. This is where we are searching for the sub-string with all unique chars.
- If the current char is part of curStr, then we need to move our search window to the right:
- Re-initialize curStr to an empty string and
- update the for loop index with re-start index.
- increment the re-start index.
As the window is moving right, keep computing max sub-string length in a max
variable. When the for loop exits, the max
variable is our answer. See the code sample below:
public int lengthOfLongestSubstring(String input) {
// if input is empty then return 0
if(input.equals("")) {
return 0;
}
int maxx = 1;
// index from where we need to re-start the for loop
int reStartIdx = 0;
// this is where we'll store the sub-strings
String curStr = "";
int count = 1;
// iterate till last input char
for(int i=0; i<input.length(); i++) {
// read the current char
char nextChar = input.charAt(i);
// if curStr doesn't contain this char
if(curStr.indexOf(nextChar) == -1) {
// append to curStr
curStr = curStr + input.charAt(i);
// update count with sub-string length
count = curStr.length();
// compare with a max variable and update
if(count > maxx) {
// this ensures that maxx always contains our answer
maxx = count;
}
}
// if curStr contains this char
else if (curStr.indexOf(nextChar) != -1) {
// re-initialize the curStr to empty string
curStr = "";
// update the for loop index with new index and go back in the loop
i=reStartIdx;
// update re-start index for next time
reStartIdx++;
}
}
return maxx;
}
You can checkout the code from Github here: Longest substring – First Approach. See the performance of this approach below:
Approach – 2
Lets try to improve on the above performance by using a Hashmap that stores the characters and their updated occurrence.
- Initialize the left and the right indices to zero. This controls our sliding window.
- Iterate in a while loop. Check if the incoming char exists in Hashmap or not. If it doesn’t exist, then add to the Hashmap with its position.
- If it already exists in the Hashmap then we need to update our window:
- check if the position of current char is greater than left index.
- if yes then increment the left char.
- Compare the
max
variable with window length and take the greater length and store back inmax
. - Increment the right window forward.
See the code sample below:
public int lengthOfLongestSubstring(String input) {
// if input is empty then return 0
if(input.equals("")) {
return 0;
}
// Map that stores char and its latest occurrence
Map<Character, Integer> charMap = new HashMap<>();
int len = input.length();
// right index
int right = 0;
// left index
int left = 0;
// sub-string length
int max = 0;
// while right index is less that input length
while (right < len ) {
// if map contains current char
if (charMap.containsKey(input.charAt(right)) ) {
// then update left index
if(charMap.get(input.charAt(right)) >= left) {
left = charMap.get(input.charAt(right)) + 1;
}
} // end if
// else if map doesn't contain current char
charMap.put(input.charAt(right), right);
// compare max with window length and update
max = Math.max(max, right - left + 1);
// increment right index
right++;
} // end while
return max;
}
You can checkout the code from Github here – Longest substring – Second Approach. See the performance of this approach below: