
首先,还是暴力破解。外循环是子串长度,从长度1开始,内循环则是子串第一个元素的下标。思路就是从长度为1的子串开始找,如果能找到不重复的,就把子串长度+1,重新找一遍,一直到子串长度为n的时候找不到无重复子串的时候返回n-1。
其中有2个细节,一个在长度为n的时候,如果已经找到了无重复子串,直接跳到下一个循环;另一个则是,每次内循环结束,要比较这次的长度和上一轮是否一样,如果一样,说明长度不再更新,直接返回即可。
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s.isEmpty()){
return 0;
}
if(s.length() == 1){
return 1;
}
int result = 0;
int tempResult = 0;
for(int strLength = 1; strLength < s.length()+1; strLength++){
for(int firstLndex = 0; firstLndex + strLength < s.length()+1; firstLndex++){
String curStr = s.substring(firstLndex, firstLndex + strLength);
char[] c = curStr.toCharArray();
Arrays.sort(c);
boolean hasSame = false; //判断子字符串中有没有相同元素
for(int i = 0; i < c.length-1; i++){
if(c[i] == c[i+1]){
hasSame = true;
}
}
//如果当前子字符串已经没有相同元素,后续也不用判断了,直接进入下一轮
if(!hasSame){
tempResult = strLength;
break;
}
}
//如果循环结果出来的长度和上一轮一样,说明已经得到最长的了
if(tempResult == result){
return result;
} else{
result = tempResult;
}
}
return result;
}
}

看了艾府的视频讲解,理解了一下思路,大致就是维护一个滑动窗口。左指针最开始指着0,然后右指针从0递增,每次递增时更新最大长度。当得到第一个重复的元素时,左指针开始递增,直到无重复元素,然后再继续递增右指针。这样重复下来,就可以得到全部的无重复子串,取最长的长度即可。(判断有无重复元素只需要拿一个hashset来记录就行)。因为这样子基本上就是遍历了2遍数组,时间为O(n),速度提升了很多。
class Solution {
public int lengthOfLongestSubstring(String s) {
HashSet<Character> set = new HashSet<>();
int result = 0;
int left = 0;
char[] c = s.toCharArray();
for(int right = 0; right<s.length(); right++){
while(true){
char curChar = c[right];
if(!set.contains(curChar)){
result = Math.max(result, right – left + 1);
set.add(curChar);
break;
}else{
if(c[left] == curChar){
left++;
break;
} else{
set.remove(c[left]);
left++;
}
}
}
}
return result;
}
}

看了一下答案优化了一下原本的方法。因为ascii码一共就128个字符,因此可以直接用一个布尔数组来判断是否遇到了重复的字符。逻辑也简化了一下,在数组中存在当前右指针指向的元素的时候,加一个while循环来移动左指针,直到去掉重复元素c的时候,再把右指针指向的元素c加进去。
class Solution {
public int lengthOfLongestSubstring(String s) {
int result = 0;
int left = 0;
char[] charStr = s.toCharArray();
boolean[] has = new boolean[128];
for(int right = 0; right<s.length(); right++){
char c = charStr[right];
//如果窗口里原本有c,则在加入之前先移除原来的c
while(has[c]){
has[charStr[left]] = false;
left++;
}
has[c] = true;
result = Math.max(result, right – left + 1);
}
return result;
}
}




