LeetCode003 Longest Substring Without Repeating Characters
we just need to return the number of that longest substring.
substring problem, maybe sliding window?
and we need to sliding over till the end to make sure we get the longest one. but for every substring we count as a potential answer, we need to make sure that it only contains unique chars. if we are checking it in a brute force way, the time complexity for this solution will be O(n2)
so is it possible that I can check it efficiently?
the time complexity for checking this is O(n), now we have to decrease it into O(1) or O(logn)
can we do it in logn? that means we have to binary search it to find out the last position of duplicate? of course not.
so can we do it in 1? well, it impossible to do it in O(long), how can we expect in O(1)? the answer is: when the substring is totally random. it is not possible, but if we can make sure that head and tail of this sliding window are unique all the time, the sliding window will always be legal? the answer is no. just use abb as example with initial pointer on a and the first b. you will find out what went wrong.
so we need to use a subtle way, and here come to using time-space trade off. and we need to checking if a char is unique in current substring. so we are thinking of using hashmap.
so we using two pointers, start and end, and we will use a variable called counter to monitor the number of duplicates of current substring. and we use maxLen to monitor the current max length of longest substring.
so the complete idea will be:
there will be two loops. the out loop will controlled by end, and the inner loop will be controlled by the number of duplicates in current substring. so each time when end is moving, we will check if there exist such a key in the map, and if there is, then we add 1 on duplicateCounter. and then, we need to make some trim on starting part, we will check starting char is duplicate, and if it is, then we update hashmap and duplicateCounter. there might be a little point that might went wrong, is that we dong’t need to use while as the inner loop because the duplicateCounter will only be from 1 to 0. well you actually got that right. we don’t need two while, the inner while loop can be changed as an if.
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) {
return 0;
}
HashMap<Character, Integer> map = new HashMap<>();
int start = 0;
int end = 0;
int maxLen = 0;
int duplicateCounter = 0;
while (end < s.length()) {
Character charEnd = s.charAt(end);
if (map.containsKey(charEnd) && map.get(charEnd) > 0) {
duplicateCounter++;
}
map.put(charEnd, map.getOrDefault(charEnd, 0) + 1);
end++;
if (duplicateCounter>0) {
Character charStart = s.charAt(start);
if (map.containsKey(charStart) && map.get(charStart) > 1) {
duplicateCounter--;
}
map.put(charStart, map.get(charStart) - 1); //we must have a key called chaStart
start++;
}
maxLen = Math.max(maxLen, end - start);
}
return maxLen;
}
}
. and we can use int[128] to make replacement on hashmap.
besides, this problem can also be saved in queue(because sliding window is just like a queue, and what we want is a consecutive substring) or we can do it using hashset to check if set contains such char, if it contains, we will removing the starting element. if it is not, we will get the size of current hashset.
HashSet way:
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s== null || s.length() == 0) return 0;
if(s.length() == 1) return 1;
int res = 0;
HashSet<Character> set = new HashSet<>();
int i = 0;
int j = 0;
while (i < s.length()) {
if(set.contains(s.charAt(i))){
set.remove(s.charAt(j));
j++;
i--;
} else {
set.add(s.charAt(i));
res = Math.max(res, set.size());
}
i++;
}
return res;
}
}

浙公网安备 33010602011771号