水果成篮问题

举报
掘金安东尼 发表于 2022/10/17 09:15:59 2022/10/17
【摘要】 题目你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采...

image.png

题目

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。

你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:

你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。

示例 1:

输入:fruits = [1,2,1]
输出:3
解释:可以采摘全部 3 棵树。

示例 2:

输入:fruits = [0,1,2,2]
输出:3
解释:可以采摘 [1,2,2] 这三棵树。
如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。

示例 3:

输入:fruits = [1,2,3,2,2]
输出:4
解释:可以采摘 [2,3,2,2] 这四棵树。
如果从第一棵树开始采摘,则只能采摘 [1,2] 这两棵树。

示例 4:

输入:fruits = [3,3,3,1,2,1,1,2,3,3,4]
输出:5
解释:可以采摘 [1,2,1,1,2] 这五棵树。

题解

思路:用滑动窗口遍历fruits,当有新种类的水果进入窗口时

如果窗口中只有一种水果,将这种水果加入arr数组

如果有两种水果,更新窗口的左边界,更新arr中水果的种类

如果进来了一种新的类型的水果 更新前一种水果的位置

更新滑动窗口的最大值

复杂度:时间复杂度O(n)

空间复杂度O(1)。

JS 实现:

//[1,1,2,2]
//[1,1,2,2,3] -> [2,2,3]
var totalFruit = function(fruits) {
    let l = 0;//起始指针
    let maxLen = 0;//窗口的最大长度 其中最多包涵两种水果
    let n = 0//前一类水果的结束位置
    let arr = [fruits[l]]//水果的种类数组

    for(let r = 0; r < fruits.length; r++){//窗口的右指针不断前进
        if(!arr.includes(fruits[r])){//如果窗口中不包含 进窗口的水果
            if(arr.length <= 1){//如果只有一种水果
                arr[1] = fruits[r]//将这种水果加入arr数组
            }else{//如果有两种水果
                l = n//更新窗口的左边界
                arr[0] = fruits[r-1]//更新arr中水果的种类
                arr[1] = fruits[r]
            }
        }
       
        if(fruits[r] !== fruits[n]){//如果进来了一种新的类型的水果 更新前一种水果的位置
            n = r
        }

        maxLen = Math.max(maxLen,r-l+1)//更新滑动窗口的最大值
    }
    return maxLen

};

总结

也可以利用 map 的有序特点:

function totalFruit(fruits: number[]): number {
    // 左指针
    let p = 0
    // 函数返回的最大值
    let max = 0
    // Map 记录水果类型(key)和最新对应的索引值(value)
    const fruitsMap: Map<number, number> = new Map()
    for (let i = 0; i < fruits.length; i++) {
        const fruit = fruits[i]
        if (fruitsMap.has(fruit)) {
            // 利用 Map 的有序性,将 Map 中已有的水果删除后再重新添加,保证最新访问的水果在 Map 的最后面
            fruitsMap.delete(fruit)
        } else {
            if (fruitsMap.size === 2) {
                // 如果访问到第三种水果类型,此时需要删除最久未访问过的水果
                // 取 Map 中第一个水果的信息(就是最久未访问过的水果)
                const iterator = fruitsMap.entries()
                const [firstFruit, firstFruitIndex] = iterator.next().value
                // 此时左指针应该指向 Map 中 第一个水果类型的索引加 1(也就是第二个水果类型的起始位置)
                p = firstFruitIndex + 1
                // 删除 Map 中第一个水果
                fruitsMap.delete(firstFruit)
            }
        }
        fruitsMap.set(fruit, i)
        max = Math.max(i - p + 1, max)
    }
    return max
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。