目录
1. 题目描述
2. Naive Approach-枚举遍历
3. 优化实现
1. 题目描述
给你一个下标从 0 开始的字符串 text
和另一个下标从 0 开始且长度为 2
的字符串 pattern
,两者都只包含小写英文字母。
你可以在 text
中任意位置插入 一个 字符,这个插入的字符必须是 pattern[0]
或者 pattern[1]
。
注意,这个字符可以插入在 text
开头或者结尾的位置。
请你返回插入一个字符后,text
中最多包含多少个等于 pattern
的 子序列 。
子序列 指的是将一个字符串删除若干个字符后(也可以不删除),剩余字符保持原本顺序得到的字符串。
示例 1:
输入:text = "abdcdbc", pattern = "ac" 输出:4 解释: 如果我们在 text[1] 和 text[2] 之间添加 pattern[0] = 'a' ,那么我们得到 "abadcdbc" 。
那么 "ac" 作为子序列出现 4 次。
其他得到 4 个 "ac" 子序列的方案还有 "aabdcdbc" 和 "abdacdbc" 。
但是,"abdcadbc" ,"abdccdbc" 和 "abdcdbcc" 这些字符串虽然是可行的插入方案,但是只出现了 3 次 "ac" 子序列,所以不是最优解。
可以证明插入一个字符后,无法得到超过 4 个 "ac" 子序列。
示例 2:
输入:text = "aabb", pattern = "ab" 输出:6 解释: 可以得到 6 个 "ab" 子序列的部分方案为 "aaabb" ,"aaabb" 和 "aabbb" 。
提示:
1 <= text.length <= 10^5
pattern.length == 2
text
和pattern
都只包含小写英文字母。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximize-number-of-subsequences-in-a-string
著作权归领扣网络所有。
商业转载请联系官方授权,非商业转载请注明出处。
先做一个傻傻的算法至少有两个作用:(1)帮助理解问题的要点,尤其是(可能的)性能瓶颈要点;(2) 提供一个验证的benchmark,傻傻的办法比较容易保证功能正确,而“聪明”的解决方案则可能很难直接判断正确性和完备性。
用pattern[0]和pattern[1]分别插入输入序列的text.length+1个可能的位置,总共2*(text.length+1)种情况,针对每种情况分别统计其中包含的子序列等于pattern的个数。
解决了遍历问题,还有一个内层的问题需要解决,即(插入一个字符后的)字符串包含多少个pattern的统计方法。
由于要保证pattern[0]和pattern[1]的顺序,可以以字符串中出现的每个pattern[0]去找出现在它之后的pattern[1]的次数,这就是由某个pattern[0]能够构造出来的子序列个数,然后再累计每个pattern[0]的子序列个数即可。
代码如下:
class Solution:
def maximumSubsequenceCount(self, text: str, pattern: str) -> int:
def countSubSeq(t):
p0_cnt = 0
subseq_cnt = 0
for k in range(len(t)):
if t[k] == pattern[0]:
p0_cnt += 1
if t[k] == pattern[1]:
subseq_cnt += p0_cnt
return subseq_cnt
subseq_max = 0
for k in range(len(text)+1):
t_tmp = text[:k] + pattern[0] + text[k:]
subseq_cnt = countSubSeq(t_tmp)
# print(t_tmp,subseq_cnt)
subseq_max = subseq_cnt if subseq_max
其中,countSubSeq()的实现还有一点点小小的trick,从头到尾遍历查找pattern[0]个数记为p0_cnt,同时查找pattern[1],每次找到一个pattern[1],就给总的计数值加一个当前p0_cnt即可。
做完了以上方案,可以发现,如果要插入pattern[0]的话那就应该要在所有pattern[1]之前;同样,如果要插入pattern[1]的话,就要插入在所有pattern[1]之后。
那就很简单了,只需要考虑将pattern[0]插入在头上,以及,pattern[1]插入在尾部两种情况就可以了。
剩下的就是同样调用countSubSeq()进行统计,并比较两种情况子序列个数取其较大者即可。
class Solution:
def maximumSubsequenceCount(self, text: str, pattern: str) -> int:
def countSubSeq(t):
p0_cnt = 0
subseq_cnt = 0
for k in range(len(t)):
if t[k] == pattern[0]:
p0_cnt += 1
if t[k] == pattern[1]:
subseq_cnt += p0_cnt
if pattern[0] == pattern[1]:
subseq_cnt = p0_cnt * (p0_cnt - 1) // 2
return subseq_cnt
subseq_cnt0 = countSubSeq(pattern[0] + text)
subseq_cnt1 = countSubSeq(text + pattern[1])
return subseq_cnt0 if subseq_cnt0>=subseq_cnt1 else subseq_cnt1
细心的小伙伴看到这里可能已经注意到了countSubSeq()的实现跟上一节相比有了一点点修改。
原因在于上一节的写法漏了一种特殊情况没有考虑,以致于出现统计错误,这个bug被leetcode的testcase精准抓捕。
具体是哪种特殊情况呢?留给小伙伴们思考。
测试代码如下:
if __name__ == '__main__':
sln = Solution()
text = "abdcdbc"
pattern = "ac"
print(sln.maximumSubsequenceCount(text, pattern))
text = "aabb"
pattern = "ab"
print(sln.maximumSubsequenceCount(text, pattern))
text = "mffiqmrvjmkfmbnaivajzecfdta"
pattern = "hh"
print(sln.maximumSubsequenceCount(text, pattern))
text = "fwymvreuftzgrcrxczjacqovduqaiig"
pattern = "yy"
print(sln.maximumSubsequenceCount(text, pattern))
回到主目录:笨牛慢耕的Leetcode解题笔记(动态更新。 。 。 )
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)