LeetCode 3:Longest Substring Without Repeating Characters
题目描述:Longest Substring Without Repeating Characters
对字符串和数组问题可以采用滑动窗口的方法
解题过程
看到这题时,想到了kmp算法。
直接对s进行扫描,当没有重复时,记录到字符串中,并声明max记录最长子串的长度,用以判断。如果,遇到重复的字符时,则判断该子串是否为当前最长子串;并将指针移动到与之重复的字符之后,减少循环次数。
public int lengthOfLongestSubstring(String s) {
if (s.length()==0||s.length()==1) {
return s.length();
}
int k=0;
int max=0;
String ssString="";
while(k<s.length()) {
ssString+=s.charAt(k);
int j=k+1;
for(;j<s.length();j++) {
if (ssString.indexOf(s.charAt(j))==-1) {
ssString+=s.charAt(j);
}
else {
k=s.indexOf(s.charAt(j),k)+1;
break;
}
}
if (max<ssString.length()) {
max=ssString.length();
}
ssString="";
if (max>=s.length()-k||j==s.length()-1) {
break;
}
}
return max;
}
题解:
滑动窗口
滑动窗口是数组/字符串问题中常用的抽象概念。 窗口通常是在数组/字符串中由开始和结束索引定义的一系列元素的集合。
使用 HashSet 作为滑动窗口, 将字符存储在当前窗口 [i, j)最初 j = i)中。 然后我们向右侧滑动索引 j,如果它不在 HashSet 中,也就是当前窗口没有重复字符时,继续滑动 ,也就是j++。直到 s[j] 已经存在于 HashSet 中,出现了重复字符。此时,找到的没有重复字符的最长子字符串将会以索引 i 开头。如果对所有的 i这样做,就可以得到答案。
但是,还可以继续进行优化,定义字符到索引的映射,使用HashMap。如果找到重复的字符时,就可以立即跳过该窗口。
也就是说,如果 s[j]在 [i, j) 范围内有与 j’重复的字符,则不需要逐渐增加 i 。 可以直接跳过 [i,j’]范围内的所有元素,并将 i 变为 j’ + 1。
public int lengthOfLongestSubstring(String s) {
int max=0;
Map<Character, Integer> map=new HashMap<Character, Integer>();
for(int j=0,i=0;j<s.length();j++) {
if (map.containsKey(s.charAt(j))) {
i=Math.max(map.get(s.charAt(j)), i);
}
max=Math.max(j-i+1, max);
map.put(s.charAt(j), j+1);
}
return max;
}
时间复杂度:O(n),索引 j 将会迭代 n 次。
空间复杂度(HashMap):O(min(m, n))。