首先先上原題:
在剛看到這道題的時候,也許對於題目的意思能夠進行很好的理解。即本題想要實現的是給定一字串,尋找出最大的無重複子串。但是,我們在面對題目所給樣例如abcabcbb或是pwwekw這樣的包含重複子串的整串時,如果能夠將重複的子串進行適當的刪除操作。這便是本題中最為核心的部分。那麼如果我們需要尋找到乙個最大的無重複子串,首先我們需要做便是遍歷操作,遍歷操作可以用for語句來進行實現。此時,針對是否重複這個問題,我們便可以利用in方法來實現對重複元素的判定操作。如果所遍歷的元素存在於對應的列表中,我們可以將字串最左邊的下標向右移動一位,實現了對重複元素的特定刪除操作;反之如果不在,則我們也可以進行類似的操作,即最右邊的下標向右移動一位,實現了對最大無重複子串的更新操作;同時更新最大無重複子串長度的更新操作,即完成了對當前子串是所需尋找的目標。而這一更新和刪除操作,我們可以通過設定兩個相應左右(雙)指標來完成對應的檢索操作,這便是針對本題最為廣為流行的一種方法:利用**雙指標(滑動視窗)**來實現對字串中最大公共子串的查詢方法。基本該思想,本文給出方法1和方法2的兩種形式的雙指標(滑動視窗)演算法**。
class
solution
:def
lengthoflongestsubstring
(self, s:
str)
->
int:
length = left = right =
0while right <
len(s)
:# 利用列表的切片方法判斷對應的字元是否在當前最大非重複子串內:
# 1、如果不在,則右指標向右移動一位,同時完成對當前最大非重複子串長度的更新
if s[right]
notin s[left:right]
: right +=
1 length =
max(length , right - left)
# 2、如果在的話,則左指標向右移動一位,完成對應的刪除操作。
else
: left +=
1return length
該演算法在執行器裡面執行消耗時間和消耗記憶體空間如下圖所示:
class
solution
:def
lengthoflongestsubstring
(self, s:
str)
->
int:
occ =
set(
) n =
len(s)
# 設定移動指標和最大無重複字串長度
rlink , length =-1
,0for i in
range
(n):
# 只有檢測到出現重複公共子串時,才會進入此操作,刪除對應的字元
if i !=0:
occ.remove(s[i]
)# 當遍歷到的字元不存在於滑動視窗,那麼就將對應檢索的字元加到滑動視窗當中
while rlink +
1< n and s[rlink +1]
notin occ:
occ.add(s[rlink +1]
) rlink +=
1 length =
max(length , rlink - i +1)
return length
該演算法在執行器裡面執行消耗時間和消耗記憶體空間如下圖所示:
class
solution
:def
lengthoflongestsubstring
(self, s:
str)
->
int:
# 字串為空則返回零
ifnot s:
return
0 max_length ,left, right =
0# 滑動視窗陣列
for i, c in
enumerate
(s):
# 如果字元不在滑動視窗中,則直接擴充套件視窗
if c not
in s[left:right]
:# 右指標右移一位
right +=
1# 如果字元在滑動視窗中,則
# 1、 從視窗中移除重複字元及之前的字串部分
# 2、 再擴充套件視窗
else
:# 在滑動視窗範圍內中找出對應的首個字元的索引x,對應的新的左指標位置為x + 1
# 左指標右移 索引x增一位
left += s[left:right]
.index(c)+1
# 擴充套件視窗大小
right +=
1# 更新最大長度
max_length =
max(right - left, max_length)
# 返回最大無重複子串有兩種長度:
# 1、如果最大長度不為零,返回最大長度
# 2、如果最大長度仍為零,則說明遍歷整個字串都沒有發現重複字元,最大長度即為字串本身的長度
return max_length if max_length !=
0else
len(s)
該演算法在執行器裡面執行消耗時間和消耗記憶體空間如下圖所示:通過此題可以看出,在面對各式各樣演算法問題的時候,我們更多的應該學會的是將該問題化解成求解n個子問題的步驟。以此來簡化求解問題的每個步驟。並加以考量可能存在的邊界條件;逐步將每乙個步驟轉化成對應的程式語言所能表達的小模組,然後將每個功能進行拼接。這便能完成對演算法的求解過程。所以說,演算法難,不在於我們所面對的問題是否無比複雜,而更多的在於,我們是否能將乙個整的大問題逐步的分解成每個小問題。這便是演算法的微妙核心所在。 LeetCode習題總結 演算法(5)
首先先上原題 通過給定對應七種羅馬數字對應的七種字元 i,v,x,l,c,d 和 m 以及對應七種字元所對應的數值 i 1,v 5,x 10,l 50,c 100,d 500,m 1000。去求解在給定乙個羅馬字串時,對應的羅馬數字表示為多少。思路 基於此題目,我們可以發現對應的羅馬字元和羅馬數字之...
LeetCode習題總結 演算法(10)
首先先上原題 拿到這道題,我們採取以下的思想來處理這個問題 1 是否特定的子串在正串中存在?2 如果不存在,我們應該返回什麼樣的數值?3 如果存在,我們該怎樣找尋子串在正串中第一次出現的位置?當我們拿到這道題時,如果能把以下幾道題能夠思考明白,想必這道題的難度係數也不會太大。那我們以此來思考上述的幾...
六一兒童節之LeetCode習題總結 演算法(14)
首先先上原題 背景闡述 輸入 candies 2,3,5,1,3 extracandies 3 輸出 true,true,true,false,true 解釋 孩子 1 有 2 個糖果,如果他得到所有額外的糖果 3個 那麼他總共有 5 個糖果,他將成為擁有最多糖果的孩子。孩子 2 有 3 個糖果,如...