904. 水果成篮

  1. 水果成篮
    你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。
    你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
    你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
    你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
    一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
    给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。

1.滑动窗口

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        unordered_map<int,int>m;
        int start=0,sum=0,res=0;
        for(int i=0;i<fruits.size();i++){
            m[fruits[i]]++;
            sum++;
            //如果m中类型大于2,逐个减少fruit[start]计数,减少到0时删去。同时start不断右移
            while(m.size()>2){
                m[fruits[start]]--;
                sum--;
                if(m[fruits[start]]==0){
                    m.erase(fruits[start]);
                }
                start++;
            }
            res=max(res,sum);
        }
        return res;
    }
};

2.按块扫描

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int n=fruits.size();
        vector<int>blockLeft;
        blockLeft.push_back(0);
        for(int i=1;i<n;i++){
            if(fruits[i]!=fruits[i-1]){
                blockLeft.push_back(i);
            }
        }
        blockLeft.push_back(n);//最后一个值无实际意义
        int start=0,sum=0,i;
        int res=0;
        while(i<blockLeft.size()-1){
            map<int,int>m;
            for(i=start;i<blockLeft.size()-1;i++){
                int type=fruits[blockLeft[i]]; //blochLeft[i]表示第i块的起始下标,在fruits中是对应类型
                m[type]++;
                if(m.size()>2){
                    start=i-1;//i是当前块,新的起始块一定是i前面的块。只剩两个块是合法的
                    res=max(res,sum);
                    sum=0;//sum清零
                    break;
                }
                sum+=blockLeft[i+1]-blockLeft[i];//加上当前块的权重
            }
        }
        return max(res,sum);
    }
};
class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int n=fruits.size();
        int res=0;
        int left=0,right=1;
        int sum=1;
        int type[2];
        type[0]=fruits[0];
        type[1]=-1;
        map<int,int>m;
        while(left<n && right<n){
            m[fruits[right]]=right;//更新最后一次出现的位置
            if(type[1]==-1){
                if(fruits[right]!=type[0]){
                    type[1]=fruits[right];
                }
                sum++;
            }else if(fruits[right]==type[0] || fruits[right]==type[1]){
                sum++;
            }else if(fruits[right]!=type[0] &&fruits[right]!=type[1]){
                res=max(res,sum);
                int tmp1=m[type[0]],tmp2=m[type[1]];
                if(tmp1>tmp2){
                    left=tmp2+1;
                    type[1]=fruits[right];
                }else{
                    left=tmp1+1;
                    type[0]=fruits[right];
                }
                sum=right-left+1;
            }
            right++;
        }
        res=max(res,sum);
        return res;
    }
};

你可能感兴趣的:(leetcode,leetcode)