题目:
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
解析
我看到这题,就知道肯定是要遍历一遍t的。而且s在t中的相对位置不变,所以:
- 当s的字符在t中出现了,那就只用考虑在此之后的序列了。因为相对位置不变。
class Solution:
def isSubsequence(self, s: str, t: str) -> bool:
length = len(s)
j = 0
if len(s) == 0:
return True
if len(s) !=0 and len(t) == 0:
return False
for i in t:
if i == s[j]:
j += 1
if j == length:
# 当j等于length,
# 说明s的字符按照相对顺序,都出现在s中,,提前return
return True
return False
另外写了一种用map的方法。适合要判断多个子序列问题。
- 先遍历一次t,用哈希表记录每个字符出现的位置。
- 遍历一次s。用tag记录s中字符在前一个字符对应的t中的位置之后最近的位置。比如前一个s中的字符在t中第i个位置出现了。那么tag为i。寻找s中后一个字符在t的第i+1之后,最先出现当前遍历s得到的字符的在t中的位置。把这个位置再次赋值给tag。还是能按顺序比较。
- 其中二分查找是为了寻找第一个符合要求的字符。
class Solution:
def isSubsequence(self, s: str, t: str) -> bool:
dic = {}
for i, a in enumerate(t):
if not dic.get(a, None):
dic[a] = []
dic[a].append(i)
tag = -1
for i in range(len(s)):
pos = dic.get(s[i], None)
if pos is None:
return False
head, tail =0, len(pos)-1
while head < tail:
mid = (head + tail) >> 2
if pos[mid] > tag:
tail = mid
else:
head = mid + 1
if tail < head or pos[head] < tag:
return False
tag = pos[head]
return True