LeetCode 904: 水果成篮(中等)

LeetCode 904: 水果成篮(中等)
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

解法

代码一:按块扫描+滑动窗口

手动模拟一下感觉不难,自己写代码感觉总有很多琐碎的细节
一开始按块扫描为了思路简单,但是按照代码二也不难

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        if(fruits.size() == 0) return 0;

        int bucket[2] = {0,0};
        int cnt[100005]={0}, type[100005]={0}, last=0, idx=0;
        type[0] = fruits[0];
        
        // type用来表示水果类型,cnt用来表示该种水果的数量, 最后数组长度为idx
        // 按块扫描,表示成(type[i], cnt[i])的形式
        for(int i=0; i<fruits.size(); i++){
            if(fruits[i] == fruits[last]) {
                cnt[idx]++;
            }
            else{
                cnt[++idx]++;
                type[idx] = fruits[i];
                last = i;
            }
        }
        
        // idx==0说明只有一种水果
        if(idx == 0) return cnt[0];

        int collect = cnt[0]+cnt[1], ans=collect;
        bucket[0] = type[0];
        bucket[1] = type[1];
        // bucket是一个大小为2的滑动窗口,注意是有序的,

        for(int i=2; i<=idx; i++){
            // 当前水果同bucket[0]的相同,可以累加,需保证bucket内部有序
            if(type[i] == bucket[0]){
                bucket[0] = bucket[1];
                bucket[1] = type[i];
                collect += cnt[i];
                ans = max(collect, ans);
            }
            // 当前水果同bucket[0]的不同,需丢掉bucket[0]类型的水果
            // eg:fruits=[0,1,0,1,2], type=[0,1,0,1,2], cnt=[1,1,1,1,1], 当前i=4,bucket=[0,1]
            // 需要将水果0丢掉,此时留下来的水果数量为cnt[i-1](这个要想明白)
            else{
                collect = cnt[i-1];
                bucket[0] = bucket[1];
                bucket[1] = type[i];
                collect += cnt[i]; 
                ans = max(collect, ans);
            }
        }
        return ans;
    }
};

在这里插入图片描述

代码二:直接滑动窗口,不要按块扫描

实际上没必要先扫描一遍,滑动窗口从左边开始消除的时候,每消除一个,就判断当前水果种类数量,比如[0,1,0,1,2],消除第一个0后水果0并没有都丢掉,因为窗口大小为2,如果当前窗口中含有水果2,则之前的水果只能是水果1,好像从水果2从右往左添加连续的水果1也行。

class Solution {
public:
    int totalFruit(vector<int>& tree) {
        unordered_map<int, int> bucket;// 建立水果类型到数量的对应
        int ans = 0, cnt = 0, left = 0;

        for (int i = 0; i < tree.size(); i++) {
            bucket[tree[i]]++;
            cnt++;
            
            // 开始从滑动窗口左边消除, bucket.size()为水果种类数量,eg:[0,1,0,1,2]
            while (bucket.size() > 2) {
                bucket[tree[left]]--;
                // 该中类型的水果丢完了
                if (bucket[tree[left]] == 0) bucket.erase(tree[left]);
                left++;
                cnt--;
            }
            ans = max(ans, cnt);
        }
        return ans;
    }
};

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值