今天這道題,看起來是否是很簡單?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)
,而這種是至關耗時的,並且會隨着字符串長度的增加,耗時也線性增長。
而聰明的人,則是經過維護一個字典,來存放惟一值,和惟一值的最大索引。對執行速度的提高,能夠說是很是顯著的。