今天这道题,看起来是否是很简单?ide
但作为一道中等难度的题目,它可不会让你失望。敲起你的键盘,试着来解下这道题,你会很难找到一个好的思路。学习
事实上,想这个思路也确实花了我很多的时间,是写代码时间的好几倍。spa
首先,要理解 子串
和 子序列
的区别。3d
子串:必须同时具有,连续性和惟一性。
子序列:只须具有惟一性便可。code
先说下个人思路。blog
假设一个字符串的长度是10,那我就先从字符串的[0,1]子串查起,假如子串里没有重复字符(经过set()
去重查看),就继续查看子串[0,2],若是仍是没有重复,就继续查看[0,3],这时候,咱们发现这个子串里有重复字符(比方说,子串"abcb"),接下来,咱们就要找出是在重复的那个字符的索引(查出是 b,在索引 1 处)。那下次咱们查找的子串就不是[0,5]了,而是[2,5],就这样一直往下,直到遍历完整个字符串。索引
class Solution:
def lengthOfLongestSubstring(self, s):
if len(s) == 1:
return 1
reset_start= False
start = 0
max_len = 0
for i in range(len(s)):
# reset_start就为True,须要从新设置起点
if reset_start:
start = new_start
# 为何加1,是由于第一次start会和end同样是0
end = i + 1
sub_str = s[start:end]
len_sub_str= end - start
if len(set(sub_str)) != len_sub_str:
# 找出是在哪一个位置重复
rep_index = sub_str.index(s[i])
new_start = rep_index + start + 1
reset_start= True
continue
if len_sub_str > max_len:
# 记录下迄今为止最在长度
max_len = len_sub_str
skip = False
return max_len
运行一下,结果不好。只击败了24.73%
。今天吃不了鸡腿了。不太小明真的是尽力了。只能想到这个思路。
ip
按照惯例,还得上网去学习别人的优秀代码。ci
真是惊叹,果真是思路决定出路啊。字符串
这种解法很巧妙。
定义两个变量longest
和left
,longest
用于存储最长子字符串的长度,left
存储无重复子串左边的起始位置。
而后建立一个哈希表,遍历整个字符串,若是字符串没有在哈希表中出现,说明没有遇到过该字符,则此时计算最长无重复子串,当哈希表中的值小于left,说明left位置更新了,须要从新计算最长无重复子串。每次在哈希表中将当前字符串对应的赋值加1。
class Solution(object):
def lengthOfLongestSubstring(self, s):
longest = 0; left = 0; tmp = {}
for index, each in enumerate(s):
if each not in tmp or tmp[each] < left:
# 计算当前最长的长度
longest = max(longest, index - left + 1)
else:
left = tmp[each]
tmp[each] = index + 1
return longest
运行一下,看看吧,击败了92.3%
。众望所归啊。 佩服佩服。
其实个人思路,和上面那个优秀代码的思路是一致的。
我作得很差的一点是,在检测当前子串是否重复这一点上面,我选了一个效率很是低的作法,就是每次循环都要计算下len(set(str_obj))
和 len(str_obj)
,而这种是至关耗时的,并且会随着字符串长度的增加,耗时也线性增长。
而聪明的人,则是经过维护一个字典,来存放惟一值,和惟一值的最大索引。对执行速度的提高,能够说是很是显著的。