這道題目可使用不少種解法,包括是動態規劃等等。html
s爲匹配字符串,t爲給定字符串假設dp[i][j]表示t從開始到第i個字符時對應s從開頭到第j個字符,s所否是t的子序列。python
分析:在比較的過程當中,若是t[i]不等於s[j],則忽略掉當前的字符,取以前i-1匹配的狀況,若是是相等,則取決於雙方上一位的匹配的狀況,這裏注意的是,若是匹配字符串爲空,那麼結果爲True。web
class Solution(object):
def isSubsequence(self, s, t):
"""
:type s: str
:type t: str
:rtype: bool
"""
if not s and not t:
return True
elif not s and t:
return True
elif not t and s:
return False
m, n = len(t), len(s)
dp = [[False for i in range(n + 1)] for j in range(m + 1)]
dp[0][0] = True
for i in range(1, m + 1):
dp[i][0] = True
for i in range(1, n + 1):
dp[0][i] = False
for i in range(1, m + 1):
for j in range(1, n + 1):
if t[i-1] == s[j-1]:
dp[i][j] = dp[i - 1][j - 1]
else:
dp[i][j] = dp[i - 1][j]
return dp[m][n]
但由於空間的複雜度過大致使了TLE,因此須要再進一步的進行優化,由於咱們只使用到了上一行的狀態,所以咱們能夠只使用兩行,而後使用完的時候進行交換便可。數組
class Solution(object):
def isSubsequence(self, s, t):
"""
:type s: str
:type t: str
:rtype: bool
"""
if not s and not t:
return True
elif not s and t:
return True
elif not t and s:
return False
m, n = len(t), len(s)
dp = [[False for j in range(m + 1)] for i in range(2)]
for i in range(m + 1):
dp[0][i] = True
for i in xrange(1, n+1):
for j in xrange(1, m+1):
if s[i-1] == t[j-1]:
dp[1][j] = dp[0][j-1]
else:
dp[1][j] = dp[1][j-1]
dp[0] = dp[1][:]
return dp[1][m]
可是,依舊是TLE,咱們繼續在它的基礎之上進行優化,由於只有在不相等的狀況的時候纔會使用到上一行的狀態,並且只用到了它的值,所以,咱們使用一個變量來進行維護。app
不會
一開始我看到這個方法的時候,竟然傻傻的去對字符串進行搜索😳。函數
思路:紀錄給定字符串每一個字符對應的位置,維護前一個字符的位置,而後遍歷匹配字符串去找到比前一個字符位置要大的位置,可是又不能超出數組長度,由於這樣顯然是由於前一個字符在不存在。優化
import collections
class Solution(object):
def isSubsequence(self, s, t):
"""
:type s: str
:type t: str
:rtype: bool
"""
def binary_search(nums, x):
low, high = 0, len(nums)
while low < high:
mid = (low + high) // 2
if nums[mid] < x:
low = mid + 1
else:
high = mid
return high
if not s and not t:
return True
elif not s and t:
return True
elif not t and s:
return False
pre_idx = 0
idxs = collections.defaultdict(list)
for i,n in enumerate(t):
idxs[n].append(i)
for i in range(len(s)):
idx = binary_search(idxs[s[i]], pre_idx)
if idx != len(idxs[s[i]]):
pre_idx = idxs[s[i]][idx] + 1
else:
return False
return True
其實上面的作法也是貪心的思想,只要後者比前者大就更新,那這裏就直接使用內建函數index
。ui
class Solution(object):
def isSubsequence(self, s, t):
"""
:type s: str
:type t: str
:rtype: bool
"""
if not s and not t:
return True
elif not s and t:
return True
elif not t and s:
return False
pre_idx = -1
for i in range(len(s)):
idx = t.find(s[i], pre_idx+1)
if idx != -1:
pre_idx = idx
else:
return False
return True
移動窗口本質也是貪心的思想,以前的動態規劃時間複雜度爲O(n^2),二分搜索優化到了O(nlogn),滑動窗口則直接優化到了O(n)。spa
思路:每當匹配字符串中的字符和給定字符串中的字符相等時,則移動匹配下標,其他均移動給定字符串下標,查看最後移動下標是否到達最後。code
class Solution(object):
def isSubsequence(self, s, t):
"""
:type s: str
:type t: str
:rtype: bool
"""
if not s and not t:
return True
elif not s and t:
return True
elif not t and s:
return False
m, n = len(s), len(t)
si, ti = 0, 0
while si < m and ti < n:
if s[si] == t[ti]:
si += 1
ti += 1
return si == m