破解 leetcode 904:装水果的篮子 - 巧用滑动窗口法,篮满为盈
2023-11-13 22:03:57
如何破解 LeetCode 904:装水果的篮子
破解 LeetCode 904
作为算法竞赛爱好者,我们经常面对各种难题,其中 LeetCode 904「装水果的篮子」就是一道令人头疼的题目。它要求我们找到最多不同种类的水果,同时满足特定限制条件。破解这道题的关键在于掌握强大的算法策略——滑动窗口法。
滑动窗口法
滑动窗口法是一种动态规划技术,用于解决寻找特定子数组的问题。它的本质是使用一个窗口在数组中移动,并在移动过程中不断更新窗口内的信息。通过这种方式,我们可以高效地找到满足特定条件的子数组。
破解步骤
解决 LeetCode 904 的具体步骤如下:
- 初始化窗口: 以窗口大小为 2,遍历数组,记录窗口内的不同水果种类数。
- 滑动窗口: 移动窗口,每移动一步,更新窗口内的信息:
- 如果窗口内水果种类数少于 2,则扩大窗口。
- 如果窗口内水果种类数达到 2,则缩小窗口,直到窗口内水果种类数减少为 1。
- 记录最大种类数: 在窗口移动过程中,记录窗口内不同水果种类数的最大值。
代码示例
为了加深理解,我们提供一个用 Java 编写的代码示例:
import java.util.HashMap;
import java.util.Map;
public class Solution {
public int totalFruit(int[] fruits) {
if (fruits == null || fruits.length == 0) {
return 0;
}
int left = 0, right = 0, maxFruit = 0, count = 0;
Map<Integer, Integer> fruitCount = new HashMap<>();
while (right < fruits.length) {
if (fruitCount.size() <= 2) {
fruitCount.put(fruits[right], fruitCount.getOrDefault(fruits[right], 0) + 1);
maxFruit = Math.max(maxFruit, ++count);
right++;
} else {
while (fruitCount.size() > 2) {
int leftFruit = fruits[left];
fruitCount.put(leftFruit, fruitCount.get(leftFruit) - 1);
if (fruitCount.get(leftFruit) == 0) {
fruitCount.remove(leftFruit);
}
left++;
count--;
}
}
}
return maxFruit;
}
}
实例分析
考虑数组 [1, 2, 1]
,使用滑动窗口法:
- 窗口初始大小为 2,窗口为
[1, 2]
。 - 移动窗口,窗口变为
[2, 1]
。 - 窗口内水果种类数为 1,扩大窗口,窗口变为
[2, 1, 2]
。 - 移动窗口,窗口变为
[1, 2, 2]
。 - 窗口内水果种类数为 2,缩小窗口,窗口变为
[1, 2]
。 - 窗口内水果种类数为 2,再次缩小窗口,窗口变为
[1]
。 - 窗口内水果种类数为 1,记录最大种类数为 2。
常见问题解答
- 为什么滑动窗口法适用于这个问题?
答:滑动窗口法适用于这个问题,因为它允许我们以高效的方式维护窗口内的水果种类数,并动态地调整窗口的大小以满足特定条件。
- 窗口大小是否可以任意设置?
答:窗口大小可以根据问题要求进行调整。对于 LeetCode 904,窗口大小设置为 2,因为题目限制我们最多携带两种不同的水果。
- 缩小窗口时如何决定删除哪个水果?
答:在缩小窗口时,我们通常删除窗口左端的最左边的水果。这样可以确保窗口内保持两种不同的水果,并防止窗口内水果种类数超过限制。
- 如何优化代码?
答:优化代码的一个方法是使用双指针(left 和 right)来维护窗口,而不是使用额外的哈希表来存储水果计数。这可以减少空间复杂度并提高运行时效率。
- LeetCode 904 还有哪些其他解法?
答:除了滑动窗口法之外,解决 LeetCode 904 还有其他解法,例如哈希表法和前缀和法。然而,滑动窗口法通常是解决这类问题的最有效方法。
结论
掌握滑动窗口法是破解 LeetCode 904 的关键。通过理解其工作原理和应用,我们可以轻松解决这类「寻找子数组」问题,并进一步提高我们的算法竞赛技能。