48 最长不含重复字符的子字符串
题目
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。假设字符串中只包含′a′′a′~′z′′z′的字符。例如,在字符串"arabcacfr""arabcacfr"中,最长的不含重复字符的子字符串是"rabc""rabc"或者"acfr""acfr",长度为4。
C++ 题解
动态规划,用f(i)表示以i个字符结尾不包含重复子字符串的最长长度,从左向右扫描:
- 若第i个字符在之前没出现过,则 f(i) = f(i-1) + 1;
- 若第i个字符在之前出现过,计算第i个字符距离上次出现之间的距离为d:
- 若d <= f(i-1),则说明第i个字符上次出现在f(i-1)对应的不重复字符串之内,那么这时候更新 f(i) = d
- 若d > f(i-1),则无影响,f(i) = f(i-1) + 1
例如arabcacfr
:
f(0) =1, a
f(1) = 2, ar
f(2) = 2, ra,因为d=2,f(1)=2,所以上一个a在f(1)之中
f(3) = 3, rab
f(4) = 4, rabc
f(5) = 3, bca,因为d=3,f(1)=4,所以上一个a一定在f(4)中
f(6) = 2, ac
f(7) = 3, acf
f(8) = 4, acfr,因为d=7,f(7)=3,因此上一个r不在f(7)中,f(8) = f(7) + 1
int longestSubstringWithoutDuplication(const std::string& str)
{
int curLength = 0;
int maxLength = 0;
//存放26个英文字符的数组,初始化为-1,表示该字符还没有出现过
int* position = new int[26];
for (int i = 0; i < 26; ++i)
position[i] = -1;
for (int i = 0; i < str.length(); ++i)
{
int prevIndex = position[str[i] - 'a'];
// 该字符没有出现过,或者是d>f(i-1)
if (prevIndex < 0 || i - prevIndex > curLength)
++curLength;
// 该字符出现过
else
{
if (curLength > maxLength)
maxLength = curLength;
// f(i) = d
curLength = i - prevIndex;
}
position[str[i] - 'a'] = i;
}
if (curLength > maxLength)
maxLength = curLength;
delete[] position;
return maxLength;
}
python 题解
class Solution:
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
start=0
maxLength=0
usedChar={}
for i in range(len(s)):
if s[i] in usedChar and start<=usedChar[s[i]]:
start=usedChar[s[i]]+1
else:
maxLength=max(maxLength,i-start+1)
usedChar[s[i]]=i
return maxLength