前置:
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
from typing import List
class Solution:
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
sum=0
i=0
temp = float('inf')
for j in range(len(nums)): # 遍历数组种每一个item,并累加
sum+=nums[j]
while sum>=s: # 满足目标条件后,开始缩小窗口
L = j-i+1
temp = min(temp,L)
# 目标是计算sum>=s时的最小窗口程度,该目标与while条件一直,所以写在while里面
# 并在窗口左边界变化之前就计算窗口大小
sum-=nums[i]
i+=1
if temp==float('inf') :return 0
else:return temp
s=Solution()
print(s.minSubArrayLen(s=7,nums=[2,3,1,2,4,3]))
print(s.minSubArrayLen(s=4,nums=[1,4,4]))
print(s.minSubArrayLen(s=11,nums=[1,1,1,1]))
你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits
表示,其中 fruits[i]
是第 i
棵树上的水果 种类 。
你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
给你一个整数数组 fruits
,返回你可以收集的水果的 最大 数目。
from collections import defaultdict
from typing import List
class Solution:
def totalFruit(self, fruits: List[int]) -> int:
a,i=len(fruits),0
tree=0
temp=0
dic_tree = defaultdict(int)
for j in range(a): # 从左到右遍历每一个item,对每个item计数并将数据放入字典
dic_tree[fruits[j]]+=1
if dic_tree[fruits[j]] == 1:
tree+=1 # 树的数量+到1时,意味着有新类型的树增加
while tree>2: # 树的类型超过2种时,开始缩小窗口
dic_tree[fruits[i]]-=1
if dic_tree[fruits[i]]==0:
tree-=1
i+=1
temp=max(temp,j-i+1)
# 目标是计算tree<=2时窗口的大小,该目标与上文while条件不一致,所以写在while之外
return temp
s=Solution()
print(s.totalFruit(fruits=[0,1,2,1]))
print(s.totalFruit(fruits=[1,2,1]))
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
例1:s='ababaa' 最长子串是 ab ,长度为2
例2:s='cccccc' 最长子串是 c ,长度为1
例1:s='dvdf' 最长子串是 vdf ,长度为3
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
temp_s=set()
j=-1
temp=0
# 遍历窗口左边界
for i in range(len(s)):
#窗口右边界 in set,就会跳出while循环,从for开始继续遍历左边界(收缩窗口左边界)
if i!=0:
temp_s.remove(s[i-1])
# 遍历窗口右边界
# 窗口右边界一旦 not in set,就继续扩展右边界
while j + 1 < len(s) and s[j + 1] not in temp_s:
temp_s.add(s[j+1])
j+=1
temp = max(temp,j-i+1)
return temp
s=Solution()
print(s.lengthOfLongestSubstring(s='dvdf'))
给定两个字符串 s
和 p
,找到 s
中所有 p
的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
# 以p_len长度的数据作为窗口
# 窗口内字符计数 == p串的字符计数 时,满足题目要求,返回窗口左边界
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
res = []
s_len,p_len = len(s),len(p)
s_count=[0]*26
p_count=[0]*26
for i in range(p_len): # p_len长度时,初始窗口字符计数、p串字符计数
s_count[ord(s[i])-97]+=1
p_count[ord(p[i])-97]+=1
if s_count == p_count:
res.append(0)
for i in range(s_len - p_len): # 窗口右移
s_count[ord(s[i])-97]-=1 # 左边界变化,旧字符计数-1
s_count[ord(s[i+p_len])-97]+=1 # 右边界变化,新字符计数+1
if s_count==p_count:
res.append(i+1)
return res
给定一个字符串 s
和一个字符串数组 words
。 words
中所有字符串 长度相同。
s
中的 串联子串 是指一个包含 words
中所有字符串以任意顺序排列连接起来的子串。
words = ["ab","cd","ef"]
, 那么 "abcdef"
, "abefcd"
,"cdabef"
, "cdefab"
,"efabcd"
, 和 "efcdab"
都是串联子串。 "acdbef"
不是串联子串,因为他不是任何 words
排列的连接。返回所有串联子串在 s
中的开始索引。你可以以 任意顺序 返回答案。
# 窗口内数据:words元素的组合
# 窗口总长度:words元素个数m * 单个元素长度n = total_l
##### words单词计数 == 窗口单词计数 时,满足题目要求
# 如何从s获取窗口:对s切片,即s[i:i+total_l]
# 如何从窗口中切分出单词:通过步长确定单词长度(0,total_l,n),对窗口切片w[j:j+n]
from typing import List
from collections import Counter
class Solution:
def findSubstring(self, s: str, words: List[str]) -> List[int]:
res = []
m, n, ls = len(words), len(words[0]), len(s)
total_l = m*n # 窗口总长度
cnt = Counter(words) # 对words单词计数
for i in range(ls-n+1):
w = s[i:i+total_l] # 切片,切出一个窗口
tmp = []
for j in range(0,total_l,n): # 按步长(单词长度)切分窗口,获取窗口内的单词
tmp.append(w[j:j+n])
if Counter(tmp) == cnt: # 窗口单词计数 == wordes单词计数时,返回窗口左边界i
res.append(i)
return res
if __name__ == '__main__':
s=Solution()
print(s.findSubstring(s='barfoothefoobarman',words=["foo","bar"]))
其他:
Count() 用法