Leetcode 904. 水果成篮

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 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] 这五棵树。

提示:

  • 1 <= fruits.length <= 10^5
  • 0 <= fruits[i] < fruits.length

我的想法:
最开始想着暴力输出,最后一个测试案例没过,就那个数组前面一堆的 0 的那个测试案例。

# Python3
class Solution:
    def totalFruit(self, fruits: List[int]) -> int:
        left = right = 0
        timemax = 0
        fruitlist = list()
        while right < len(fruits):
            if fruits[right] not in fruitlist:
                fruitlist.append(fruits[right])
                while 1:
                    if len(set(fruitlist)) > 2:
                        fruitlist.pop(0)
                    else:
                        break
            else:
                fruitlist.append(fruits[right])
            timemax = max(timemax, len(fruitlist))
            right += 1
        return timemax

后来想着滑动窗口和双指针:
第一种:
left = right = 0,fruitlist 用来收集水果种类
[1,0,1,4,1,4,1,2,3]
右移 right
timemax = max(timemax, right-left + 1) = 3
[1,0,1,4,1,4,1,2,3]
当 right 指向 4 的时候,fruitlist 长度为3,让 left 指向 fruitlist 的第二种,即 0 。
[1,0,1,4,1,4,1,2,3]
取 fruitlist 的第一种,即 1。如果 1 和 right 前一个值相同的话,即 1 和 1 相同。
取 fruitlist 的第二种,即0。如果 0 在 fruits[left:right] 中,left 右移,将 0 从 fruitlist 删去。fruitlist 里为 1 和 4。
[1,0,1,4,1,4,1,2,3]
右移 right ,之后同理。

第二种:
left = right = 0,fruitlist 用来收集水果种类
[3,3,3,1,2,1,1,2,3,3,4]
右移 right
timemax = max(timemax, right-left + 1) = 4
[3,3,3,1,2,1,1,2,3,3,4]
当 right 指向 2 的时候,fruitlist 长度为 3,让 left 指向 fruitlist 的第二种,即 1 。
[3,3,3,1,2,1,1,2,3,3,4]
取 fruitlist 的第一种,即 3。如果 3 和 right 前一个值不同的话,即 3 和 1 不同。
如果 3 在 fruits[left:right] 中,left 右移。这里不在,将 3 从 fruitlist 删去。fruitlist 里为 1 和 2。
右移 right
timemax = max(timemax, right-left + 1) = 5
[3,3,3,1,2,1,1,2,3,3,4]
当 right 指向 3 的时候,fruitlist 长度为 3,让 left 指向 fruitlist 的第二种,即 2 。
[3,3,3,1,2,1,1,2,3,3,4]
取 fruitlist 的第一种,即 1。如果 1 和 right 前一个值不同的话,即 1 和 2 不同。
如果 1 在 fruits[left:right] 中,left 右移。
[3,3,3,1,2,1,1,2,3,3,4]
将 1 从fruitlist 中删去

class Solution:
    def totalFruit(self, fruits: List[int]) -> int:
        left = right = 0 # left、right先都指向列表第一位
        timemax = 0 # 收集的水果的最大数目
        fruitlist = list() # 收集水果种类的列表
        n = len(fruits)
        while right < n:
            if fruits[right] not in fruitlist: 
                fruitlist.append(fruits[right])
            if len(fruitlist) <= 2: 
                timemax = max(timemax, right-left + 1)
            elif len(fruitlist) > 2: 
                left = left + fruits[left:right].index(fruitlist[1]) 
                string = fruitlist[0]
                if string != fruits[right - 1]: 
                    while string in fruits[left:right]:
                        left += 1
                    fruitlist.pop(0)
                else:
                    string = fruitlist[1]
                    while string in fruits[left:right]:
                        left += 1
                    fruitlist.pop(1)
            right += 1
        return timemax

粘一个官方题解,比我想的简单多了。
在这里插入图片描述
Python3:

class Solution:
    def totalFruit(self, fruits: List[int]) -> int:
        cnt = Counter()

        left = ans = 0
        for right, x in enumerate(fruits):
            cnt[x] += 1
            while len(cnt) > 2:
                cnt[fruits[left]] -= 1
                if cnt[fruits[left]] == 0:
                    cnt.pop(fruits[left])
                left += 1
            ans = max(ans, right - left + 1)
        
        return ans

作者:力扣官方题解
链接:https://leetcode.cn/problems/fruit-into-baskets/solutions/1893352/shui-guo-cheng-lan-by-leetcode-solution-1uyu/

C++:

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int n = fruits.size();
        unordered_map<int, int> cnt;

        int left = 0, ans = 0;
        for (int right = 0; right < n; ++right) {
            ++cnt[fruits[right]];
            while (cnt.size() > 2) {
                auto it = cnt.find(fruits[left]);
                --it->second;
                if (it->second == 0) {
                    cnt.erase(it);
                }
                ++left;
            }
            ans = max(ans, right - left + 1);
        }
        return ans;
    }
};

C:

#define MAX(a, b) ((a) > (b) ? (a) : (b))

typedef struct {
    int key;
    int val;
    UT_hash_handle hh;
} HashItem; 

HashItem *hashFindItem(HashItem **obj, int key) {
    HashItem *pEntry = NULL;
    HASH_FIND_INT(*obj, &key, pEntry);
    return pEntry;
}

bool hashAddItem(HashItem **obj, int key, int val) {
    if (hashFindItem(obj, key)) {
        return false;
    }
    HashItem *pEntry = (HashItem *)malloc(sizeof(HashItem));
    pEntry->key = key;
    pEntry->val = val;
    HASH_ADD_INT(*obj, key, pEntry);
    return true;
}

bool hashSetItem(HashItem **obj, int key, int val) {
    HashItem *pEntry = hashFindItem(obj, key);
    if (!pEntry) {
        hashAddItem(obj, key, val);
    } else {
        pEntry->val = val;
    }
    return true;
}

int hashGetItem(HashItem **obj, int key, int defaultVal) {
    HashItem *pEntry = hashFindItem(obj, key);
    if (!pEntry) {
        return defaultVal;
    }
    return pEntry->val;
}

void hashFree(HashItem **obj) {
    HashItem *curr = NULL, *tmp = NULL;
    HASH_ITER(hh, *obj, curr, tmp) {
        HASH_DEL(*obj, curr);  
        free(curr);             
    }
}

int totalFruit(int* fruits, int fruitsSize){
    HashItem *cnt = NULL;
    int left = 0, ans = 0;
    for (int right = 0; right < fruitsSize; ++right) {
        hashSetItem(&cnt, fruits[right], hashGetItem(&cnt, fruits[right], 0) + 1);
        while (HASH_COUNT(cnt) > 2) {
            HashItem *pEntry = hashFindItem(&cnt, fruits[left]);
            pEntry->val--;
            if (pEntry->val == 0) {
                HASH_DEL(cnt, pEntry);
                free(pEntry);
            }
            ++left;
        }
        ans = MAX(ans, right - left + 1);
    }
    hashFree(&cnt);
    return ans;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值