您的位置:首页 > 其它

[LeetCode - 滑动窗口] 3. Longest Substring Without Repeating Characters

2017-05-02 18:55 501 查看

1 问题

Given a string, find the length of the longest substring without repeating characters.

Examples:

Given “abcabcbb”, the answer is “abc”, which the length is 3.

Given “bbbbb”, the answer is “b”, with the length of 1.

Given “pwwkew”, the answer is “wke”, with the length of 3. Note that the answer must be a substring, “pwke” is a subsequence and not a substring.

2 分析

定理1:长度为n的字符串的所有子字符串的数量为: n(n+1)2

证明:以字符串 “abcde” 为例:

以第一个字符 ‘a’ 开头的子字符串个数为 5

以第二个字符 ‘b’ 开头的子字符串个数为 4

以第三个字符 ‘c’ 开头的子字符串个数为 3

以第四个字符 ‘d’ 开头的子字符串个数为 2

以第五个字符 ‘e’ 开头的子字符串个数为 1

根据以上规律可以得出长度为n的字符串的所有子字符串的个数是1+2+3+...+n=O(n2)

因此,如果列举出所有的子字符串后再判断最大的长度的子字符串,那么效率不够高。通过观察不含重复字符的子字符串的特征有:

令 Si,j 表示以i为起点,以j为终点的不含有重复字符的子字符串(j对应的字符不在子串中, 例如”abcde”中,S1,3表示 “ab”), Si,j+1的长度与Si,j的长度有如下的关系:

如果字符S(j)包含在Si,j中, 那么Si,j+1因为含有重复字符而不符合题目的要求

如果字符S(j)不包含在Si,j中, 那么Si,j+1的长度等于Si,j的长度+1

这样就可以用滑动窗口方法,处理这一类字符串、数组问题。

滑动窗口方法包括两个主要操作

向左(右)扩展

向左(右)收缩

具体做法请参考:what is sliding window algorithm

3 伪代码

left, right
代表窗口的左右边界,将
left, right
初始化为0

初始化空哈希表
hs
,表的键为
left,right
表示的窗口中不重复的字符值

初始化
maxLen=0
, 表示最长的不重复子串的长度

执行以下循环,循环的结束条件是:
right >= len(s)
,
s
表示题目给出的字符串

判断
s(j)
是不是在
hs
中:

如果是,那么将
s(left)
hs
中删除, 并执行
left=left+1
,将窗口左边界向右收缩

如果否,那么将
s(right)
加入
hs
中, 并执行
right=right+1
, 将窗口右边界向右扩展, 同时更新
maxLen = right - left


在循环结束后,返回
maxLen


时间复杂度:在算法执行的过程中,
left
,
right
分别遍历一遍
s
,故时间复杂度是O(2n)。

4 Java代码

public class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length();
Set<Character> set = new HashSet<>();
int ans = 0, i = 0, j = 0;
while (i < n && j < n) {
// try to extend the range [i, j]
if (!set.contains(s.charAt(j))){
set.add(s.charAt(j++));
ans = Math.max(ans, j - i);
}
else {
set.remove(s.charAt(i++));
}
}
return ans;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: