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;
    }
};
经验分享 程序员 微信小程序 职场和发展