给定一个字符串,找到最长子字符串的长度而不重复字符。
Input: 'pwwkew'
Output: 3(wke)
Method 1 找到所有substring中长度最大的
1. 建立一个变量用来存储最大字符串长度(maxlen=0)
2. 两个for循环, 一个设定为子字符串的开头(i)另一个为了遍历它后面所有的字符(j),如果j与前面的字符重复就停止第二层循环。
3. 每次遍历完j之后, 都要比较一下当前的字符串长度与之前运算过的字符串长度的最大值
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
l=len(s)
maxlen=0
for i in range(l):
dummy=[s[i]]
for j in range(i+1,l):
if s[j] not in dummy:
dummy.append(s[j])
else:
break
maxlen=max(maxlen,len(dummy))
return maxlen
'''
maxlen dummy
2 ['p', 'w']
2 ['w']
3 ['w', 'k', 'e']
3 ['k', 'e', 'w']
3 ['e', 'w']
3 ['w']
3
'''
时间复杂度O(n³)因为每次都要检查子字符串是否有唯一的字符所以将有n*(n+1)/2个字符串
Method 2 滑动窗口Sliding Windows
1. 建立一个dic字典存储s中字母(j)和其对应的位置(i), maxlen用来存储最大长度, start用来做滑动窗口开始的指针
{ dic={}; maxlen=0; start=0 }
2. 先判断字母是否存在于字典中。
如果字母j存在字典中,那么start就从s中重复字母的下一个开始。but考虑到会出现s='adda'这种情况,当处理到最后一位时,a在前面出现,start如果start等于之前出现a的位置的后一位时会变成选取dda这种情况。所以start应该选取当前已经处理到的滑动窗口的位置和字母j对应位置的最大值。
如果不存在于字典中,那么把字母和其在s中的对应位置存入字典,更新最大长度即:当前字母位置i-滑动窗口起始位置start+1(因为位置是从0开始的)。由于之前可能存在不重复的子字符串长度比现在的长,所以要取之前maxlen和现在的最大值
{for i,j in enumerate(s): if j in dic: start=max(start, dic[j]+1); dic[j]=i; maxlen=max(maxlen, i-start+1)}
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
dic={}
maxlen=0
start=0
for i,j in enumerate(s):
if j in dic:
start=max(start,dic[j]+1)
dic[j]=i
maxlen=max(maxlen,i-start+1)
return maxlen
时间复杂度O(n)只需要遍历完s中的字符串就可以了。
Java
和Python相似, 设置左右两个指针
class Solution {
public int lengthOfLongestSubstring(String s) {
int res=0;
char[] c = s.toCharArray();
Map<Character, Integer> map = new HashMap<>();
for (int i = 0, j = 0; i < c.length; i++) {//j代表左指针
j = map.containsKey(c[i]) ? Math.max(j, map.get(c[i])) : j;//当map中存在当前遍历的字符时, 左指针更新
map.put(c[i], i + 1);
res = Math.max(res, i - j + 1);
}
return res;
}
}