class Solution:
def countGoodSubstrings(self, s: str) -> int:
l = len(s)
if l<=2:
return 0
ans = 0
for i in range(2,l):
if s[i-2] != s[i-1] and s[i-1] != s[i] and s[i-2] != s[i]:
ans+=1
return ans
暴力超时版本:
class Solution:
def distinctNumbers(self, nums: List[int], k: int) -> List[int]:
ans = []
i = 0
l = len(nums)
while i+k<=l:
ans.append(len(set(nums[i:i+k])))
i+=1
return ans
字典计数版本(只在窗口处做计数统计):
class Solution:
def distinctNumbers(self, nums: List[int], k: int) -> List[int]:
ans = []
dict_ = {}
for i in range(k):
dict_[nums[i]] = dict_.get(nums[i],0)+1
size = len(dict_)
ans.append(size)
l = len(nums)
for i in range(k,l):
dict_[nums[i]] = dict_.get(nums[i],0)+1
if dict_[nums[i]] == 1:
size+=1
dict_[nums[i-k]] -= 1
if dict_[nums[i-k]] == 0:
size-=1
ans.append(size)
return ans
class Solution:
def numKLenSubstrNoRepeats(self, s: str, k: int) -> int:
ans = 0
l = len(s)
if l<k:
return 0
dict_ = {}
for i in range(k):
dict_[s[i]] = dict_.get(s[i],0)+1
size = len(dict_)
if size == k:
ans+=1
for i in range(k,l):
dict_[s[i]]=dict_.get(s[i],0)+1
if dict_[s[i]] == 1:
size += 1
dict_[s[i-k]] -= 1
if dict_[s[i-k]] == 0:
size-=1
if size == k:
ans+=1
return ans
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
k = len(p)
l = len(s)
if l<k:
return []
ans = []
dict_k = {}
for i in p:
dict_k[i]=dict_k.get(i,0)+1
dict_ = {"a":-1,"c":1,"b":1}
dict_s = {}
for i in range(k):
dict_s[s[i]]=dict_s.get(s[i],0)+1
if dict_s == dict_k:
ans.append(0)
for i in range(k,l):
dict_s[s[i]]=dict_s.get(s[i],0)+1
dict_s[s[i-k]]-=1
if dict_s[s[i-k]]==0:
dict_s.pop(s[i-k])
if dict_s == dict_k:
ans.append(i-k+1)
return ans
分析图示参考: 分享滑动窗口模板,秒杀滑动窗口问题
class Solution:
def longestOnes(self, nums: List[int], k: int) -> int:
ans = 0
l = len(nums)
left = 0
right = 0
curr_k = 0
# right主动往右边滑动
while right<l:
if nums[right] == 0:
curr_k+=1
# 当curr_k大于k时,需要滑动left,使左边的0减少直到满足curr_k==k
while curr_k>k:
if nums[left] == 0:
curr_k-=1
left+=1
ans = max(ans,right-left+1)
right+=1
return ans
此题是上一题k=1时的特殊情况,思路完全一致。
class Solution:
def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
ans = 0
left = 0
right = 0
curr_k = 0
l = len(nums)
# right主动往右边滑动
while right<l:
if nums[right] == 0:
curr_k+=1
# 翻转一个,即当curr_k>1时,需要将left向右移动直到使curr_k=1
while curr_k>1:
if nums[left] == 0:
curr_k-=1
left+=1
ans = max(ans,right-left+1)
right+=1
return ans
此题注意两点:1)全1也需要删除一位;2)有0时,需要去掉一位0的计数;
class Solution:
def longestSubarray(self, nums: List[int]) -> int:
ans = 0
left = 0
right = 0
curr_k = 0
l = len(nums)
while right<l:
if nums[right] == 0:
curr_k+=1
while curr_k>1:
if nums[left]==0:
curr_k-=1
left+=1
# 根据实际情况:curr_k=1时,需要删除1(0的个数)
ans = max(ans,right-left+1-curr_k)
right+=1
# 有0时已经减去了,全1时,也要减去
if ans == l:
ans-=1
return ans
class Solution:
def maxConsecutiveAnswers(self, answerKey: str, k: int) -> int:
l = len(answerKey)
ret = 0
left = 0
right = 0
curr_k = 0
while right<l:
if answerKey[right] == "F":
curr_k+=1
while curr_k>k:
if answerKey[left] == "F":
curr_k-=1
left+=1
ret = max(ret,right-left+1)
right+=1
left = 0
right = 0
curr_k = 0
while right<l:
if answerKey[right] == "T":
curr_k+=1
while curr_k>k:
if answerKey[left] == "T":
curr_k-=1
left+=1
ret = max(ret,right-left+1)
right+=1
return ret
备注:需要依次遍历,每次遍历更新最大最小值。
class Solution:
def subArrayRanges(self, nums: List[int]) -> int:
L = len(nums)
ret = 0
for i in range(L):
max_,min_ = nums[i],nums[i]
for j in range(i+1,L):
max_ = max(nums[j],max_)
min_ = min(min_,nums[j])
ret += max_- min_
return ret
class RecentCounter:
def __init__(self):
self.queue = []
def ping(self, t: int) -> int:
self.queue.append(t)
# 此题严格递增,使用队列存储,只需淘汰掉超过左边范围的数即可
while self.queue[0] < t-3000:
self.queue.pop(0)
return len(self.queue)
class Solution:
def minSwaps(self, nums: List[int]) -> int:
count = nums.count(1)
L = len(nums)
ret = count
zero_count = 0
for i in range(0,L*2):
if i>=count:
ret = min(ret,zero_count)
if nums[(i-count)%L] == 0:
zero_count-=1
zero_count += 1 if nums[i%L] == 0 else 0
return ret
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
n = len(nums)
# 注意 Python 默认的优先队列是小根堆
q = [(-nums[i], i) for i in range(k)]
heapq.heapify(q)
ans = [-q[0][0]]
for i in range(k, n):
heapq.heappush(q, (-nums[i], i))
while q[0][1] <= i - k:
heapq.heappop(q)
ans.append(-q[0][0])
return ans
剑指 Offer II 016. 不含重复字符的最长子字符串
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
ret = 0
dict_ = collections.defaultdict(int)
curr = 0
for i,v in enumerate(s):
if v in dict_:
# curr只能向前更新
curr = max(dict_[v]+1,curr)
dict_[v] = i
ret = max(ret,i-curr+1)
return ret
class Solution:
def minimumRecolors(self, blocks: str, k: int) -> int:
ret = k
min_ = 0
for i in range(k):
if blocks[i] == "W":
min_+=1
ret = min(ret,min_)
for i in range(k,len(blocks)):
if blocks[i] == "W":
min_+=1
if blocks[i-k] == "W":
min_-=1
ret = min(ret,min_)
return ret
class Solution:
def takeCharacters(self, s: str, k: int) -> int:
dict_ = defaultdict(int)
dict_['a'] = 0
dict_['b'] = 0
dict_['c'] = 0
ret = -1
L = len(s)
i = L
while dict_['a'] < k or dict_['b'] < k or dict_['c'] < k:
if i == 0:
return -1
i-=1
dict_[s[i]]+=1
ret = L - i
for j in range(L):
dict_[s[j]]+=1
while i<L and dict_[s[i]] > k:
dict_[s[i]]-=1
i+=1
ret = min(ret, j+1+L-i)
if i == L:
break
return ret