题目链接:https://leetcode.com/problems/longest-substring-without-repeating-characters/#/description
题目要求:给定一个字符串,找出字符串中没有重复字符的子串的最大长度。
思路:对于字符串中的每一个字符,找出以每一个字符为最后元素的,符合条件的子串的长度,将各个子串的长度值保存起来。遍历各个子串的长度值,其中的最大值即为该字符串的符合条件的最长子串的长度。
举例来说,对于字符串“pwwkew”,
以第一个字符p为结尾的符号条件的最长子串为"p",因此记录下该子串的长度为 1;
以第二个字符w为结尾的符合条件的最长子串为“pw”,因此记录下该子串的长度为 2;
以第三个字符w为结尾的符合条件的最长子串为“w”,因此记录下该子串的长度为 1;
以第四个字符k为结尾的符合条件的最长子串为“wk”,因此记录下该子串的长度为 2;
以第五个字符w为结尾的符合条件的最长子串为“wke”,因此记录下该子串的长度为 3;
以第六个字符w为结尾的符合条件的最长子串为“kew”,因此记录下该子串的长度为 3;
遍历右侧保存的各个子串的长度值[1,2,1,2,3,3],得到该字符串的符合条件的最长子串的长度为3(子串“wke” 或 子串“kew”)
思路明确之后,本题的另外一个难点是,如果找到以字符串中某个字符(记为c)为结尾的最长子串。我的方法是:使用队列保存位于字符c之前的子串,该子串中无重复元素。在计算以c字符结尾的最长子串时,首先判断队列中是否有c字符,有的话就将队列中的c及其之前的字符全部出队列,然后将新的c入队列,这样就得到了以这个新的c为结尾的最长子串;如果队列中没有c字符,那么直接把c入队列,此时新的队列中仍然没有重复元素,符合条件,此时队列中的保存的子串就是以c为结尾的最长子串。
Java代码如下:
public class Solution {
public int lengthOfLongestSubstring(String s) {
if(s.length() == 0){
return 0;
}
int length = s.length();
int[] count = new int[length];
// 对于每一个下标i,那一时刻队列中保存的是以nums[i]为最后一个元素的不重复子串的长度值
Queue<Character> queue = new LinkedList<Character>();
for(int i=0; i<s.length(); i++){
// 当前处理的字符
char current = s.charAt(i);
// 如果队列中有和当前字符相同的字符
if(queue.contains(current)){
// 则将队列中与当前字符相同的字符及之前的字符全部出队列
while(queue.remove()!= current){
}
// 当前字符进队列
queue.add(current);
count[i] = queue.size();
} else {
// 如果队列中没有和当前字符相同的字符
queue.add(current);
count[i] = queue.size();
}
}
int max = count[0];
// 遍历count数组,其中最大的子串长度值就是整个字符串的符合条件的最大子串长度值
for(int num: count){
if(num > max){
max = num;
}
}
return max;
}
}