一、暴力法
暴力法很简单,就是双指针。一个指针left指向起始位置,另一个指针right向后查找,每当子串s.subString(left, right-1)中不包含right所指字符s.charAt(right),就将当前的字符放到此字符串中,即长度加1。直到最后找出最长的那一个,代码如下:
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s.length() == 0)
return 0;
if (s.length() == 1)
return 1;
int i = 0, j = 1, maxLength = 0;
while (i < s.length()) {
//j作为right指针,一直向后找,直到不符合为止
while (j < s.length() && !exist(i, j-1, s, s.charAt(j))) {
++j;
}
if ((j-i) > maxLength) //更新最大长度
maxLength = (j-i);
++i;
}
return maxLength;
}
private boolean exist(int start, int end, String s, char c) {
for (int i = start; i <= end; ++i) {
if (s.charAt(i) == c)
return true;
}
return false;
}
}
二、滑动窗口方法
就是说假设一个窗口内是不包含重复元素的,每次遇到一个新元素就和窗口内元素比较,若已经存在于窗口内则改变窗口的左指针,更新规则为左指针变为重复字符的最新或者说最靠近右侧的位置:
public class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length(), ans = 0;
Map<Character, Integer> map = new HashMap<>(); // current index of character
// 区间[i, j]为当前的字符串
for (int j = 0, i = 0; j < n; j++) {
if (map.containsKey(s.charAt(j))) {
//若当前元素存在于窗口内,则改变窗口左指针,取最右侧的位置
i = Math.max(map.get(s.charAt(j)), i);
}
ans = Math.max(ans, j - i + 1);
map.put(s.charAt(j), j + 1); //存放重复元素的下一个位置
}
return ans;
}
}
所以此处判断是否有重复元素的方法是使用了map,这样就判断的时间复杂度降为了O(n)。