The trivial solution would be to do double for loop and from each position try to find the longest substring until we see a duplicate char. This is O(n^2) solution.
Finding the Longest substring without repeating characters is same as finding the Longest substring with All distinct characters. So instead of K distinct characters we have to find the longest substring where all characters are distinct.
We start with a window and maintain a hashset for that window. We keep on adding chars to window and slide window to right, till they are not duplicate. If we find duplicate we keep moving the left pointer to shrink window, till we remove that duplicate char from the set. In meantime, we will keep check of the longest window.
publicintlengthOfLongestSubstring(String s) {
// Note: The Solution object is instantiated only once and is reused by each test case.int maxLength = 0;
// left is first pointer, right is second pointer HashSet<Character> set =new HashSet<Character>();
int left = 0;
int right = 0;
while (right < s.length()) {
char c = s.charAt(right);
if (set.contains(c)) {
set.remove(s.charAt(left));
left++;
} else {
set.add(c);
right++;
maxLength = Math.max(maxLength, set.size());
}
}
return maxLength;
}
publicintlengthOfLongestSubstring(String s) {
int n = s.length();
// answer - length of longest substring with no repeating charsint ans =-1;
// frequency map of chars in window Map<Character, Integer> windowCharCnt =new HashMap<>();
int left = 0;
for(int right = 0; right < n; right++) {
char c = s.charAt(right);
windowCharCnt.put(c, windowCharCnt.getOrDefault(c, 0) + 1);
while(windowCharCnt.size() < right - left + 1) {
char leftChar = s.charAt(left);
windowCharCnt.put(leftChar, windowCharCnt.get(leftChar) - 1);
if(windowCharCnt.get(leftChar) == 0) {
windowCharCnt.remove(leftChar);
}
left++;
}
if(windowCharCnt.size() == right-left+1) {
ans = Math.max(ans, right-left+1);
}
}
return maxLen;
}
Method 3 - Sliding Window with Boolean array as set 🏆#
We can use a flag array to track the existing characters for the longest substring without repeating characters.
When we realize that substring “abcc” has dups, we can immediately abandon the whole substring and check substrings from “cdefgh”. Thus, we have the following approach:
Keep two pointers (start, end) that denotes the current substring we’re checking and both has an initial value of 0.
Each time, move forward end pointer by 1 character and use the hashset to check if the newly added character has already existed.
If not, keep moving end pointer forward.
If the new character is a duplicate one, move the start pointer all the way to pass the duplicate character and pop out all these characters from the hashset.
Repeating step 2 and output the longest substring without dup after finishing the whole string.
publicintlengthOfLongestSubstring(String s) {
if (s ==null)
return 0;
boolean[] flag =newboolean[256];
int result = 0;
int start = 0;
char[] arr = s.toCharArray();
for (int i = 0; i < arr.length; i++) {
char current = arr[i];
if (flag[current]) {
result = Math.max(result, i - start);
// the loop update the new start point// and reset flag array// for example, abccab, when it comes to 2nd c,// it update start from 0 to 3, reset flag for a,bfor (int k = start; k < i; k++) {
if (arr[k]== current) {
start = k + 1;
break;
}
flag[arr[k]]=false;
}
} else {
flag[current]=true;
}
}
result = Math.max(arr.length- start, result);
return result;
}