力扣刷题笔记 长度最小的子数组以及相关题目(含ACM模式)

《代码随想录》学习笔记,原链接:https://programmercarl.com/

209.长度最小的子数组

​编辑(1)滑动窗口

(2)核心代码模式

(3)ACM模式

长度最小的子数组相关题目

(1)904.水果成篮


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)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值