Java描述 LeetCode,904. 水果成篮

本文介绍了一种使用滑动窗口算法解决水果篮子问题的方法,通过具体实例讲解了如何利用set和map实现从左到右移除超出限制的水果种类,以确保篮子中只包含两种类型的水果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

𝑰’𝒎 𝒉𝒉𝒈, 𝑰 𝒂𝒎 𝒂 𝒈𝒓𝒂𝒅𝒖𝒂𝒕𝒆 𝒔𝒕𝒖𝒅𝒆𝒏𝒕 𝒇𝒓𝒐𝒎 𝑵𝒂𝒏𝒋𝒊𝒏𝒈, 𝑪𝒉𝒊𝒏𝒂.

  • 🏫 𝑺𝒉𝒄𝒐𝒐𝒍: 𝑯𝒐𝒉𝒂𝒊 𝑼𝒏𝒊𝒗𝒆𝒓𝒔𝒊𝒕𝒚
  • 🌱 𝑳𝒆𝒂𝒓𝒏𝒊𝒏𝒈: 𝑰’𝒎 𝒄𝒖𝒓𝒓𝒆𝒏𝒕𝒍𝒚 𝒍𝒆𝒂𝒓𝒏𝒊𝒏𝒈 𝒅𝒆𝒔𝒊𝒈𝒏 𝒑𝒂𝒕𝒕𝒆𝒓𝒏, 𝑳𝒆𝒆𝒕𝒄𝒐𝒅𝒆, 𝒅𝒊𝒔𝒕𝒓𝒊𝒃𝒖𝒕𝒆𝒅 𝒔𝒚𝒔𝒕𝒆𝒎, 𝒎𝒊𝒅𝒅𝒍𝒆𝒘𝒂𝒓𝒆 𝒂𝒏𝒅 𝒔𝒐 𝒐𝒏.
  • 💓 𝑯𝒐𝒘 𝒕𝒐 𝒓𝒆𝒂𝒄𝒉 𝒎𝒆:𝑽𝑿
  • 📚 𝑴𝒚 𝒃𝒍𝒐𝒈: 𝒉𝒕𝒕𝒑𝒔://𝒉𝒉𝒈𝒚𝒚𝒅𝒔.𝒃𝒍𝒐𝒈.𝒄𝒔𝒅𝒏.𝒏𝒆𝒕/
  • 💼 𝑷𝒓𝒐𝒇𝒆𝒔𝒔𝒊𝒐𝒏𝒂𝒍 𝒔𝒌𝒊𝒍𝒍𝒔:𝒎𝒚 𝒅𝒓𝒆𝒂𝒎

题解

这个题目拿到手上,一看就知道是滑动窗口题。再看看,一个篮子里面装水果,种类最多是2,很明显就是往里面塞,重复的数字只能算一个,那么就能想到用set,关键是用了set怎么从篮子里面把那个先放进来的水果给扔出去呢?
在这里插入图片描述
如果是从左往右扔,为什么是从左往右扔呢?

你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。

题目里面的意思就是有顺序,不能跳过,就是不能一下子把[low,high]=[1,2,1,1,3]里面的某一个不连续的重复数,比如这里的2全扔掉变成[2,3]。所以这里应该扔掉1,2变成[1,1,3]就能符合新的要求。但是这个从左到右对于set是比较难以把握的,因为很难判断到底扔多少个,但是我们可以知道保留多少个呀,对不对,只要满足high之前的都是同一个数就好了。也就是[1,1,3]。蓝色的就是新的符合题意的篮子。2就是需要被扔掉的那个水果,直接从篮子里面剔除,所以前面有多少个2在这一刻都已经被丢掉了,包括2之前的1,也不要了,因为要保证low,high这个区间的连续性
在这里插入图片描述

上代码!

public int totalFruit2(int[] fruits) {
    int n = fruits.length;
    int high = 0;
    int max = -1;

    Set<Integer> set = new HashSet<>();
    int low = 0;
    while (high < n) {
        set.add(fruits[high]);
        if (set.size() > 2) { // 丢水果的过程
            low = high - 1;
            while (fruits[low - 1] == fruits[low]) {
                low--;
            }
            set.remove(fruits[low - 1]);
        }
        max = Math.max(max, high - low + 1);     // @1
        high++;
    }
    return max;
}

@1:会对每一次的[low,high]范围进行判断,这样就不会漏掉set.size==2的时候里面的各种情况,比如[1,2,1]或者是[1,2,1,1]都会被计算的,直到遇见[1,2,1,1,3],进行判断set.size() > 2直接给出下一个满足题意的[low,high]出来。注意我们讨论的[low,high]都是闭区间

这个方法来自评论区的一个兄弟,也是我的方法,但是我在篮子出现3个怎么扔水果的地方,解不出来。

官解

官解和上面的思想一样,但是通过一个map实现的从左到右扔水果的过程,代码如下:

public int totalFruit(int[] fruits) {
    int n = fruits.length;
    int low = 0, high = 0;
    int max = -1;

    Map<Integer, Integer> map = new HashMap<>();
    while (high < n) {
        map.put(fruits[high], map.getOrDefault(fruits[high], 0) + 1);
        while (map.size() > 2) { // 丢水果的过程
            map.put(fruits[low], map.get(fruits[low]) - 1);
            if (map.get(fruits[low]) == 0) {
                map.remove(fruits[low]);
            }
            low++;
        }
        max = Math.max(max, high - low + 1);
        high++;
    }
    return max;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

河海哥yyds

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值