209. 长度最小的子数组
"""
暴力求解法 两个while循环。。时间复杂度到n2 可恶超时了
"""
class Solution(object):
def minSubArrayLen(self, target, nums):
"""
:type target: int
:type nums: List[int]
:rtype: int
"""
i, j = 0, 0
num = []
if sum(nums) < target:
return 0
else:
while i < len(nums):
n = 0
j = i
while n < target and j <= len(nums)-1:
n += nums[j]
j = j + 1
if n >= target:
num.append(j-i)
i += 1
return min(num)
"""
时间复杂度为n的动态窗口法
"""
class Solution(object):
def minSubArrayLen(self, target, nums):
"""
:type target: int
:type nums: List[int]
:rtype: int
"""
i, j = 0, 0
num = []
s = 0
if sum(nums) < target:
return 0
else:
while i < len(nums):
s += nums[i]
while s >= target and j <= i:
num.append(i-j+1)
s -= nums[j]
j+=1
i += 1
return min(num)
904. 水果成篮
class Solution(object):
def totalFruit(self, fruits):
"""
:type fruits: List[int]
:rtype: int
"""
j, l = 0, 0
n = collections.Counter()
for i in range(len(fruits)):
n[fruits[i]] += 1
while (len(n) > 2):
n[fruits[j]] -= 1
if not n[fruits[j]]:
n.pop(fruits[j])
j += 1
l = max(l, i - j + 1)
return l
备注: 本质上求数组中,只包含两个不同元素的最长子字符串。这题结合哈希表做会简单,通过哈希表来控制左指针是否向右移动
76. 最小覆盖字串
class Solution(object):
def minWindow(self, s, t):
"""
:type s: str
:type t: str
:rtype: str
"""
i, j, start, end = 0, 0, 0, 0
nums = collections.Counter(t)
l = len(s) + 1
sumneed = len(t)
while i < len(s):
if s[i] in t:
if nums[s[i]] > 0: # if nums[s[i]] > 0: #这里要进行判断,只有当某个数的数量没满足要求的时候need才减1 需要注意的是当nums[s[i]]<0的时候,
说明s[i]是多余的
sumneed -= 1
nums[s[i]] -= 1
while sumneed == 0 : # 当满足要求的时候 第一步要先保存结果并比较
if i-j+1 < l:
start, end= j, i
l = i-j+1
if s[j] in t: # 第二步要判断移动j 将导致哈希表出现什么样的变化
if nums[s[j]] >= 0:
sumneed += 1
nums[s[j]] += 1
j += 1
i += 1
if l == len(s) + 1:
return ""
return s[start:end+1]
备注: 太难了。也是滑动窗口,重点是判断j移动的条件。
滑动窗口总结:
1、适合寻找数组中符合条件的连续子数组
2、一般用两个循环 外圈的while负责移动右指针,遍历更多的可能性。内圈的while判断左指针移动的条件,使得滑动窗口始终能满足题目条件