《代码随想录》学习笔记,原链接:https://programmercarl.com/
209.长度最小的子数组
(1)滑动窗口
滑动窗口也可以理解为双指针法的一种,通过不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。如当target = 7时,图示如下:
(2)核心代码模式
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
slow, fast, subSum = 0, 0, 0
subLenth = float('inf') # 子数组长度初始化为正无穷
for fast in range(0, len(nums)):
subSum += nums[fast]
while subSum >= target: # 此处为了保证起始位置持续移动,不能使用if
subSum -= nums[slow]
slow += 1
subLenth = min(subLenth, fast - slow + 1) # slow - 1和fast为最小子数组的起始和终止位置
if subLenth != float('inf'): # 判断target是否为0
return subLenth + 1 # subLenth为起始和终止位置之间的差值
return 0 # 不存在符合条件的子数组
【注】虽然代码中,for里面放了一个while,但是不要以为for里放一个while就以为是O(n^2)。主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n ,也就是O(n)。
(3)ACM模式
class Solution:
def minSubArrayLen(self, target, nums):
slow, fast, subSum = 0, 0, 0
subLenth = float('inf') # 子数组长度初始化为正无穷
for fast in range(0, len(nums)):
subSum += nums[fast]
while subSum >= target: # 此处为了保证起始位置持续移动,不能使用if
subSum -= nums[slow]
slow += 1
subLenth = min(subLenth, fast - slow + 1) # slow - 1和fast为最小子数组的起始和终止位置
if subLenth != float('inf'): # 判断target是否为0
return subLenth + 1 # subLenth为起始和终止位置之间的差值
return 0 # 不存在符合条件的子数组
# 自定义数据列表和target
nums = list(map(int, input("输入正整数列表:").split(",")))
target = int(input("输入target:"))
# 长度最小的子数组
solution = Solution()
result = solution.minSubArrayLen(target, nums)
print(result)
长度最小的子数组相关题目
(1)904.水果成篮
- 核心代码模式
class Solution:
def totalFruit(self, fruits: List[int]) -> int:
slow, fast = 0, 1 # 双指针法
fruit1, fruit2 = fruits[0], float('inf') # 记录两个篮子当前的水果种类
numType, numFruit, maxFruit = 1, 1, 1
for fast in range(1, len(fruits)):
if fruits[fast] in [fruit1, fruit2]: # 当前果树的水果种类已在篮子里
numFruit += 1
if fruits[fast] != fruits[fast - 1]: # 记录当前种类果树的起始位置
slow = fast
else: # 出现新的种类的水果
if numType == 1: # 第二个篮子还没有放水果
slow = fast
fruit2 = fruits[fast] # 记录第二个水果的种类
numType = 2
numFruit += 1
else: # 出现第三个种类的水果
maxFruit = max(numFruit, maxFruit) # 计算当前已经收集的水果的最大数目
if fruits[fast] != fruits[fast - 1]: # 记录上一个种类水果的起始位置
while fruits[slow] != fruits[fast - 1]:
slow += 1
fruit1 = fruits[slow] # 更新篮子里的水果种类
fruit2 = fruits[fast]
numFruit = fast - slow + 1
if fruits[fast - 1] in [fruit1, fruit2]: # 计算当前已经收集的水果的最大数目
maxFruit = max(numFruit, maxFruit)
return maxFruit
【注】一些部分代码块的必要性分析:
if fruits[fast] != fruits[fast - 1]: # 记录上一个种类水果的起始位置
while fruits[slow] != fruits[fast - 1]:
slow += 1
if fruits[fast - 1] in [fruit1, fruit2]: # 计算当前已经收集的水果的最大数目
maxFruit = max(numFruit, maxFruit)