904. 水果成篮(滑动窗口+动态规划)

140 阅读2分钟

image.jpeg

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第24天,点击查看活动详情

测试岗位也越来卷了,除了基本的功能测试外,还要有编程基础、脚本经验才脱颖而出。

怎么才能提高我们的编程能力呢,刷LeetCode是最佳的途径之一,话不多数,刷题走起~

一、题目描述:

  • 题目内容

    image.png

  • 题目示例

    image.png

  • 题目提示

    • 1 <= fruits.length <= 105
    • 0 <= fruits[i] < fruits.length

二、思路分析:

我们今天拿到本题是 leetcode 难度为中等题 904. 水果成篮。题目要求在fruits数组中找出符合水果类型的连续最长的数目。题目对水果类型做了限制条件如下:

  • 在fruits中找出两种水果类型的果篮中
  • 且fruits中水果在果篮中不一样时,则移除水果种类其中一个,添加到新的水果种类
  • 需要返回水果篮水果种类能包含连续数组元素最多的

根据题目描述,本题关键之处需要是求出一段连续的最长子数组长度,可以使用滑动窗口来模拟解决,同时也可以通过找规律动态规划来解答,思路如下:

  • 方法一: 滑动窗口

    • 题目要求是必须是连续数组判断水果种类,因此使用双指针right,left来控制窗口
    • 同时使用哈希表来,存储在fruits数组遍历的元素出现的次数,借助Counter()对象current
    • 当right指针遍历时,将fruit元素放入current字典中,且次数+1
    • 当current中水果种类大于2时,需要将多余的水果类型移除,left持续向右移动,当current[fruits[left]]次数持续减一,直到等于0位置将哈希表中移除该水果种类fruits[left]
    • 最大长度结果ans在right-left+1与ans取最大值更新
    class Solution(object):
        def totalFruit(self, fruits):
            """
            :type fruits: List[int]
            :rtype: int
            """
            current = Counter()
            left,ans = 0,0
    
            for right,fruit in enumerate(fruits):
    
                current[fruit] +=1
                while len(current) > 2:
                    current[fruits[left]] -=1
                    if current[fruits[left]] == 0:
                        current.pop(fruits[left])
                    left +=1
    
                ans = max(right-left+1,ans)
    
            return ans 
    
  • 方法二:动态规划

    • 在本题中始终要维护两种水果出现的dp[0]当前水果种类和dp[1]水果种类连续次数情况
    • 在本题要求连续的数组,因此需要使用a变量来记录水果2种类,有三种情况
    • 当fruits[i]不是前一颗树水果fruits[i-1],又不是水果2的种类时,则将当前水果2种类更新为fruits[i-1],当前水果类型dp[0]次数赋值为1,水果种类连续次数为dp[1]更新为dp[0]+1
    • 当fruits[i]与前一颗树水果fruits[i-1]时,则当前水果种类dp[0]+1,连续两种水果类型dp[1]+1
    • 当fruits[i]与水果2种类一样时,则当前水果dp[0]赋值为1,连续水果种类次数dp[1]+1
    class Solution(object):
        def totalFruit(self, fruits):
            """
            :type fruits: List[int]
            :rtype: int
            """
    
            dp = [1]*2
            n = len(fruits)
            a = -1
            ans = 0
            for i in range(1,n):
                if fruits[i] != fruits[i-1] and fruits[i] != a:
                    if ans < dp[1]: ans = dp[1]
                    a = fruits[i-1]
                    dp[1] = dp[0] + 1
                    dp[0] = 1
                elif fruits[i] == fruits[i-1]:
                    dp[0] +=1
                    dp[1] +=1
                elif fruits[i] == a:
                    a = fruits[i-1]
                    dp[0] = 1
                    dp[1] += 1
    
            return max(ans,dp[1])
    

三、总结:

本题是一道关于求连续最长的字串长度,是滑动窗口的应用场景,难点在于需要借用哈希表来记录元素出现的次数,并且需要判断当哈希表key大于2时,需要移动left指针,对相应的元素出现的次数进行累计求差,直到元素出现次数为0时,移除该元素,保持元素种类最多两种情况。AC提交记录如下:

image.png

  • 时间复杂度:O(n),n 为fruits的长度
  • 空间复杂度:O(1),长度为2的key-value键值对

以上是本期内容,欢迎大佬们点赞评论,下期见~~~