滑动窗口即在一个序列中维持一个窗口,这个窗口由左指针和右指针表示,使用滑动窗口可以减少大量的重复计算
2021.1.28
无重复字符的最长字串
1.使用两个指针表示字符串的某个字串。其中左指针在下面的代码中为i,右指针为rk。
2.在每一步的操作中,将左指针向右移动一格,表示开始枚举下一个字符作为起始位置,然后不断的向右移动右指针,直到遇到重复的字符,记录下字串长度。
时间复杂度:
O
(
n
)
O(n)
O(n),
n
n
n表示字符串长度
空间复杂度:
O
(
e
)
O(e)
O(e),
e
e
e表示字符集的大小
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# 哈希集合,记录每个字符是否出现过
occ = set()
n = len(s)
# 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
rk, ans = -1, 0
for i in range(n):
if i != 0:
# 左指针向右移动一格,移除一个字符
occ.remove(s[i - 1])
while rk + 1 < n and s[rk + 1] not in occ:
# 不断地移动右指针
occ.add(s[rk + 1])
rk += 1
# 第 i 到 rk 个字符是一个极长的无重复字符子串
ans = max(ans, rk - i + 1)
return ans
2021.2.22
串联所有单词的子串
这道题我想了很久,但还是在一些例子上不通过,主要的原因的窗口的维护上不够好,先贴上我写的不通过的代码
class Solution:
def findSubstring(self, s: str, words: List[str]) -> List[int]:
words = sorted(words)
length = len(words[0])
Index = []
tail = 0
i=0
for j in range(length):
i = tail = j
List = []
while(i<len(s)):
if i != 0 and s[i-length:i] in List:
List.remove(str(s[i-length:i]))
while tail+length<=len(s) and s[tail:tail+length] in words and len(List) < len(words):
List.append(str(s[tail:tail+length]))
tail = tail + length
if i == tail:
tail = tail+1
if sorted(List) == words:
Index.append(i)
i = i + length
continue
i = i+1
Index = list(set(Index))
return Index
对于"mississippi"[“si”,“is”]这种情况我的输出是[0],预期输出是[0,4]。
正确答案
class Solution:
def findSubstring(self, s: str, words: List[str]) -> List[int]:
if not s or not words:
return []
n = len(s)
one_word_len = len(words[0]) #一个单词的长度
word_cnt = len(words) #单词的个数
all_len = one_word_len * word_cnt
words_cnt = defaultdict(int) #每个单词出现的次数
for w in words:
words_cnt[w] += 1
res = []
for i in range(one_word_len): #shell希尔排序的套路 start delta = 一个单词的长度
cur_w_num = 0 #单词个数
L, R = i, i
cur_w_dic = defaultdict(int) #当前单词的次数统计
while R + one_word_len <= len(s):
w = s[R: R + one_word_len]
R += one_word_len #R每次像右移一个单词的长度 类似于shell排序中的delta
if w not in words_cnt: #结束前,出现个不知道哪里的单词,整个前面一片就废了
L = R
cur_w_dic.clear()
cur_w_num = 0
else:
cur_w_dic[w] += 1
cur_w_num += 1
while cur_w_dic[w] > words_cnt[w]:
L_w = s[L : L + one_word_len]
L += one_word_len #L右移
cur_w_dic[L_w] -= 1 #做好统计
cur_w_num -= 1
if cur_w_num == word_cnt: #如果说ok了
res.append(L)
return res
2021.2.24
1052.爱生气的书店老板
开心,这是第一道没有看答案独立完成的中等难度题目
思路很简单,把不生气时的顾客数全部加起来,然后通过滑动窗口计算窗口中生气时的顾客数的最大值。把不生气时的顾客总数加上生气时的最大值就是答案。
class Solution:
def maxSatisfied(self, customers: List[int], grumpy: List[int], X: int) -> int:
tail=0
ALL=0
MAX=0
cur=0
length = len(customers)
for i in range(length):
while tail-i<X and tail+1<=length:
if grumpy[tail]==1:
cur += customers[tail]
MAX = max(cur,MAX)
else:
ALL += customers[tail]
tail += 1
if grumpy[i]==1:
cur -= customers[i]
return ALL + MAX