日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

python 判断子序列_LeetCode 392. 判断子序列 | Python

發布時間:2024/9/19 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python 判断子序列_LeetCode 392. 判断子序列 | Python 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

392. 判斷子序列

題目

給定字符串 s 和 t ,判斷 s 是否為 t 的子序列。

你可以認為 s 和 t 中僅包含英文小寫字母。字符串 t 可能會很長(長度 ~= 500,000),而 s 是個短字符串(長度 <=100)。

字符串的一個子序列是原始字符串刪除一些(也可以不刪除)字符而不改變剩余字符相對位置形成的新字符串。(例如,"ace"是"abcde"的一個子序列,而"aec"不是)。

示例 1:

s = "abc", t = "ahbgdc"

返回 true.

示例 2:

s = "axc", t = "ahbgdc"

返回 false.

后續挑戰 :

如果有大量輸入的 S,稱作S1, S2, ... , Sk 其中 k >= 10億,你需要依次檢查它們是否為 T 的子序列。在這種情況下,你會怎樣改變代碼?

解題思路

思路:雙指針、動態規劃

在這里,先理清題目所提出的問題,題目要問的是,s 是否是 t 的子序列?而題目中定義這個子序列,是指不改變相對位置在原字符串中刪除一些(或者不刪除)字符剩余的字符。

那么也就是說,只要能找到 s 在 t 中存在(相對位置順序對應),那么可以認定 s 是 t 的子序列。例如,題目中所給出的示例,"ace" 是 "abcde" 的一個子序列,而 "aec" 不是。因為 "aec" 改變了相對位置的順序。

在這里,我們可以從前往后匹配,而且可貪心地靠前匹配出現的字符。

當我們從前往后匹配字符的時候,假設出現的字符 x 在 t 中出現的位置,一個在前面,一個在后面。在這里,應該考慮匹配 x 在 t 出現前面的字符,這是因為往后匹配,當選定前面位置出現的字符時,能夠更大概率匹配成功。(因為字符 x 出現在后面位置往后能取的字符,前面位置往后也能夠取到,而且前后兩個位置之前的字符也有可選字符。)

那么具體的算法如下:

定義雙指針 p、q,分別指向 s 和 t 的初始位置;

這里匹配前面位置出現的字符(也就是進行貪心匹配),當匹配成功之后,指針同時往后移動;

如果匹配失敗,p 保持不同,移動 q。

如果 p 能夠到達末尾,那么說明 s 就是 t 的子序列。

具體的代碼見【代碼實現 # 雙指針】

還有一個后續挑戰,需要檢驗大量的 s 是否是 t 的子序列。在上面的雙指針的方法當中,從前往后去匹配字符需要大量的時間,那么這里再使用雙指針的方法顯然不合適。

這里參考官方題解,說一下動態規劃如何去快速匹配 s 是否是 t 的子序列。

首先用動態規劃的方法去進行預處理,能夠確定在 t 的每個位置,從該位置往后每個字符第一次出現的位置。

狀態定義

設 dp[i][j] 表示字符串 t 中從 i 的位置開始往后匹配,j 第一次出現的位置。

狀態轉移方程

如果 t 中位置 i 的字符就是 j 的話,那么 dp[i][j] = i;

若不是上面的情況,那么也就是說 j 出現在 i 位置之后的某個位置(這里不包含 i),此時 dp[i][j] = dp[i+1][j]

狀態初始化

在這里,索引從 0 開始,那么 i 的取值范圍為 [0, t_len),這里不包含 t_len。那么,這里存在邊界問題,當 i = t_len-1 的時候,這里可能會無法進行轉移。我們讓 i = t_len 的時候,令 dp[t_len][...] 為 t_len,那么也就說,當 dp[i][j] = t_len 的時候,那么就表示從 i 開始無法匹配 j。

具體的代碼見【代碼實現 # 動態規劃】

代碼實現

# 雙指針

class Solution:

def isSubsequence(self, s: str, t: str) -> bool:

s_len = len(s)

t_len = len(t)

# 定義雙指針,指向 s 和 t 的初始位置

p = 0

q = 0

while p < s_len and q < t_len:

# 當 s 的字符與 t 的字符匹配時

# 同時移動 p 和 q 指針

if s[p] == t[q]:

p += 1

# 如果不匹配,只移動 q 指針,與 p 指針所對應的字符繼續匹配判斷

q += 1

# 如果 p 指針到達 s 末尾返回 True

return p == s_len

# 動態規劃

class Solution:

def isSubsequence(self, s: str, t: str) -> bool:

s_len = len(s)

t_len = len(t)

dp = [[0] * 26 for _ in range(t_len)]

# 這里是為了能夠讓 i = t_len-1 的時候能夠正常轉移

dp.append([t_len]*26)

# 在這里,從后往前枚舉,因為 dp[i][j] 可能從 dp[i+1][j] 中轉移而來

for i in range(t_len-1, -1, -1):

for j in range(26):

# 如果位置 i 的字符就是 j 時,那么 dp[i][j] = i

if ord(t[i]) == j + ord('a'):

dp[i][j] = i

else:

dp[i][j] = dp[i+1][j]

# dp[i][j] = i if ord(t[i]) == j + ord('a') else dp[i+1][j]

# 開始遍歷匹配 s,檢驗 s 的每個字符在 t 中的某個位置是否存在

idx = 0

for i in range(s_len):

# 如果轉移只有結果為 t_len,表示無法匹配字符,那么返回 False

if dp[idx][ord(s[i]) - ord('a')] == t_len:

return False

# 當找到匹配當前字符的位置之后,從這個位置的下一個位置開始查找下一個字符是否出現在 t 中的某個位置

idx = dp[idx][ord(s[i]) - ord('a')] + 1

return True

實現結果

雙指針

動態規劃

歡迎關注

公眾號 【書所集錄】

總結

以上是生活随笔為你收集整理的python 判断子序列_LeetCode 392. 判断子序列 | Python的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。