题目描述
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
- 输入:
"abcabcbb"
- 输出:
3
- 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
- 输入:
"bbbbb"
- 输出:
1
- 解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
- 输入:
"pwwkew"
- 输出:
3
- 解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是子串的长度,“pwke” 是一个子序列,不是子串
一、解法一
- 1、先遍历整个字符串
- 2、对遍历到的每次字符的后一个字符做判断(判断是否在遍历完的字符中出现过)
- 3、建立一个空字符串,如果判断的字符没有出现过,则将它加入到建立的字符串中,并记录建立的字符串的长度
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
"""
:type s: str
:rtype: int
"""
maxLength = 0 # 记录最长字符串长度
for i,_ in enumerate(s): # enumerate生成字符串迭代器,下标以及对应的字符
count = 0 # 记录字符串长度
newChar = str() # 新建字符串
for j in s[i:]: # 遍历外轮遍历字符的后面字符
if j not in newChar: # 如果没有出现
newChar += j # 追加到新建的字符串中
count += 1 # 并且长度+1
if maxLength < count: # 如果最大长度小于该长度
maxLength = count # 更新最长长度
else: # 如果出现过,退出本次内轮遍历
break
return maxLength
上面代码的算法复杂度为 O(n2)O(n^2)O(n2)
缺陷:
p w w k e w
i
j
newChar = pw
=====================================
p w w k e w
i
j
newChar = w
=====================================
p w w k e w
i
j
newChar = w
- 当内轮遍历的字符出现过,跳出内轮遍历,外轮遍历i加1,此时新建字符串少了个字符p,不可能比原本的长,因此我们可以直接跳到重复元素之后开始新的循环。
class Solution:
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
start = maxLength = 0
newChar = {}
for index, char in enumerate(s):
if char in newChar and start <= newChar[char]: # 如果出现过,更新开始位置为重复元素之后的字符开始
start = newChar[char] + 1
else: # 没有出现,更新最长长度
maxLength = max(maxLength, index - start + 1)
usedChar[char] = index
return maxLength
时间复杂度是O(n)O(n)O(n),空间复杂度也是O(n)O(n)O(n)
二、解法二(滑动窗口)
建立一个256位大小的整型数组 freg
,用来建立字符和其出现位置之间的映射。
维护一个滑动窗口,窗口内的都是没有重复的字符,去尽可能的扩大窗口的大小,窗口不停的向右滑动。
- (1)如果当前遍历到的字符从未出现过,那么直接扩大右边界;
- (2)如果当前遍历到的字符出现过,则缩小窗口(左边索引向右移动),然后继续观察当前遍历到的字符;
- (3)重复(1)、(2),直到左边索引无法再移动;
- (4)维护一个结果res,每次用出现过的窗口大小来更新结果res,最后返回res获取结果。
1、Java
代码
public class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length();
int res = 0;
int l = 0, r = 0;
Set<Character> set = new HashSet<>();
while(l < n && r < n){
if(set.contains(s.charAt(r))){
set.remove(s.charAt(l++));
}else{
set.add(s.charAt(r++));
res = Math.max(res, r - l);
}
}
return res;
}
}
2、C++
代码
class Solution {
public:
int lengthOfLongestSubstring(string s)
{
int l = 0;
int r = 0;
int maxLength = 0;
int usedChar[256] = { 0 };
while (l < s.size())
{
if (r < s.size() && usedChar[s[r]] == 0)
{
usedChar[s[r++]] += 1;
}
else
{
usedChar[s[l++]] -= 1;
}
maxLength = max(maxLength, r - l);
}
return maxLength;
}
};
3、Python
代码
class Solution:
"""
:type s: str
:rtype: int
"""
def lengthOfLongestSubstring(self, s):
l = 0
r = 0
maxLength = 0
s_len = len(s)
usedChar = [0] * 256 # 通过符号表记录符号出现次数
while l < s_len:
if r < s_len and usedChar[ord(s[r])] == 0:
usedChar[ord(s[r])] += 1
r += 1
else:
usedChar[ord(s[l])] -= 1
l += 1
maxLength = max(maxLength, r - l)
return maxLength