给定一个字符串,找到最长的子字符串的长度,不重复字符。
例子:
给定”abcabcbb”的答案是”abc”,长度是3。
给定”bbbbb”的答案是”b”,长度为1。
给定”pwwkew”的答案是”wke”,长度为3.请注意,答案必须是一个子字符串,”pwke”是一个子序列,而不是一个子字符串。
2滑动窗口[接受]
算法
天真的做法是非常简单的。但是太慢了。那么我们如何优化呢?
在天真的方法中,我们重复检查一个子字符串,看它是否有重复的字符。但是这是没有必要的。如果一个子串sij
从索引一世i去j – 1已经检查了 j – 1没有重复的字符。我们只需要检查一下S [j]的s [ j ]已经在子字符串中了sij
要检查一个字符是否已经在子字符串中,我们可以扫描子字符串,这会导致一个 为O(n ^ 2)ø (Ñ
2
)算法。但是我们可以做得更好。
通过使用HashSet作为滑动窗口,检查当前的字符是否可以在其中完成 O(1)O (1 )。
滑动窗口是数组/字符串问题中常用的抽象概念。窗口是数组/字符串中通常由开始和结束索引定义的一系列元素,即[i,j)[ i ,j )(左转,右转)。滑动窗口是将其两个边界“滑”到某个方向的窗口。例如,如果我们滑动[i,j)[ i ,j )在右边11元素,然后它成为[i + 1,j + 1)[ i + 1 ,j + 1 )(左闭,右开)。
回到我们的问题。我们使用HashSet来存储当前窗口中的字符[i,j)[ i ,j )(j = ij = 我最初)。然后我们滑动索引Ĵj在右边。如果它不在HashSet中,我们滑动Ĵj进一步。这样做直到s [j]已经在HashSet中。此时,我们发现没有重复字符的子字符串的最大尺寸以索引开始一世我。如果我们这样做的话一世我,我们得到我们的答案。
class Solution {
public int lengthOfLongestSubstring(String s) {
Set<Character> set = new HashSet<Character>();
int start =0,end =0,result =0;
int n = s.length();
while (start<n&&end<n){ if(!set.contains(s.charAt(end))){ set.add(s.charAt(end++));
result = Math.max(result,end-start);
}
else{
set.remove(s.charAt(start++));
}
}
return result;
}
}