LeetCode76-最小覆盖子串
今天早上在梅园吃完早餐
出来就天降暴雨了
骑着小电驴和康哥在雨中狂奔
不由得想起了上个学期
和康哥骑着小蓝在雨中狂奔的场景
好不快哉啊!!!
76-最小覆盖子串
给定一个字符串 S 和一个字符串 T,请在 S 中找出包含 T 所有字母的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"
说明:
- 如果 S 中不存这样的子串,则返回空字符串 ""。
- 如果 S 中存在这样的子串,我们保证它是唯一的答案。
思路:
这一题刚开始看的云里雾里的,看了网上大佬的讲解之后,才有头绪。原来就是双指针的运用,关于双指针问题,前面做过一些题目,但都没有好好总结,所以到了这道难度较高的题目时,就有些束手无策了。决定这两天把双指针问题好好总结一下,争取也写篇解题心得出来。
好了,闲话不多说。这题的核心思想应该是:用双指针来表示出一个滑动窗口,这个滑动窗口所表示的字符串 S 之子串刚好能包含 T 所有字母。不断滑动该窗口,从而找出最小的窗口值。具体的滑动过程可见下图:
顺藤摸瓜,你就会发现本题的难点就是要让你表示出这个滑动窗口,即确定该窗口的起始值和终点值。过程如下:
代码如下:
class Solution:
# 本题采用双指针法思想解决问题
def minWindow(self, s, t):
"""
:type s: str
:type t: str
:rtype: str
"""
# 创建一字典用于记录给定字符串t中相关字符的个数信息
dict_t = {}
for index in t:
if index in dict_t.keys():
dict_t[index] += 1
else:
dict_t[index] = 1
# 记录 S 中找出包含 T 所有字母的最小子串的起点位置和终点位置
min_start = 0
min_end = 2000000
# 记录 S 中找出包含 T 所有字母的子串的起点位置
current_start = 0
# 定义检索到字符串t中相关字符的个数
t_num = 0
# 遍历字符串s,使用滑窗法找出包含 T 所有字母的子串
for current_end in range(len(s)):
if s[current_end] in t:
if dict_t[s[current_end]] > 0:
t_num += 1
dict_t[s[current_end]] -= 1
# 如果t_num刚好等于len(t),即说明已经找到一组符合条件的字串了。此时记录字串的起点和终点位置
# 并继续移动窗口,查找是否有更短的字串
while t_num == len(t):
if current_end - current_start < min_end - min_start:
min_start = current_start
min_end = current_end
if s[current_start] in t:
if dict_t[s[current_start]] >= 0:
t_num -= 1
dict_t[s[current_start]] += 1
current_start += 1
return s[min_start:min_end+1] if min_end < 2000000 else ""
if __name__ == "__main__":
s = "ADOBECODEBANC"
t = "ABC"
partial_str = Solution().minWindow(s, t)
print(partial_str)
执行效率一般吧,在50%左右。如果各位读者有更好的方法还请积极留言啊!!!