这题巨难,前前后后不间断地看了三天,成功入选本人看writeup也看不懂系列。
【我巨菜】
主要的难点在于:
1、what the hell is p
2、what the hell is (index - p +1)
3、why max()?
以下先贴出答案,待我慢慢道来。
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
p = 0
res = 0
character = dict()
for index in range(len(s)):
if s[index] in character:
p = max(p,character[s[index]]+1) #p延迟指向在重复字符的后一个字符
character[s[index]] = index
newSubLength = index - p +1
res = max(res,newSubLength) #newSubLength是指新筛选的substring的长度。
return res
string = 'helloworld'
for i in range(len(string)):
print (i,string[i],end = ' ')
print ('result = ',Solution().lengthOfLongestSubstring(string))
1)首先,创建一个空字典,利用字典key-value的特性,以字符为key,字符上一次出现的index为value,进行存放。
2)for循环遍历字符串,每次循环判断该字符是否已经作为key存在字典中。
如果在,就拿p指向该字符上次出现的index的下一位。并更新字典中对应字符的value为这次的index。每次循环都会记录下当前subString的长度newSubLength,如果比res要大,那就更新res。(res是result,返回值的意思)
3)以在字符串helloworld中找最长substring为例子说明:
0h / 1e / 2l / 3l / 4o / 5w / 6o / 7r / 8l / 9d
如helloworld中,l在index=3时发现与前面index=2的l重复,character[s[index]]存的是字符上一次出现时的index,于是p通过max(p,character[s[index]]+1)就会指向第一次出现的index=2的l的后一个index=3的l,因为if语句判定index=3的l与前一次出现的l是重复字符。
index=6时,发现o与上一个index=4的o重复,于是p通过max函数,指向了o第一次出现时的index=4的后一个字符w,此时p=5。
4)这种思路相当于abcadefgh中找最长substring
当我遇到了第二个a,我应该剔除第一个a,从b开始计算后面的最长substring,而不应该指向第二个a,才开始计算后面的最长substring。
所以p应该指向b,p=1,res在index取max,即index指向h,index=8时取最大值,又因为从0开始计数,所以要加1。res = index - p + 1 = 8
substring = ‘bcadefgh’
5)其次,变量newSubLength用来存放的是:(p更新指向后)随着index增加,寻找到的最新的substring的长度,当某个时刻newSubLength比res大时,max函数会把旧的、比较小的res更新,因为每次循环都会执行max函数。