在一排树中,第 i 棵树产生 tree[i] 型的水果。
你可以从你选择的任何树开始,然后重复执行以下步骤:
1,把这棵树上的水果放进你的篮子里。如果你做不到,就停下来。
2,移动到当前树右侧的下一棵树。如果右边没有树,就停下来。
请注意,在选择一颗树后,你没有任何选择:你必须执行步骤 1,然后执行步骤 2,然后返回步骤 1,然后执行步骤 2,依此类推,直至停止。
你有两个篮子,每个篮子可以携带任何数量的水果,但你希望每个篮子只携带一种类型的水果。
用这个程序你能收集的水果树的最大总量是多少?
——————————————————————————————————————————————————————
示例 1:
输入:[1,2,1]
输出:3
解释:我们可以收集 [1,2,1]。
示例 2:
输入:[0,1,2,2]
输出:3
解释:我们可以收集 [1,2,2]
如果我们从第一棵树开始,我们将只能收集到 [0, 1]。
示例 3:
输入:[1,2,3,2,2]
输出:4
解释:我们可以收集 [2,3,2,2]
如果我们从第一棵树开始,我们将只能收集到 [1, 2]。
示例 4:
输入:[3,3,3,1,2,1,1,2,3,3,4]
输出:5
解释:我们可以收集 [1,2,1,1,2]
如果我们从第一棵树或第八棵树开始,我们将只能收集到 4 棵水果树。
提示:
1 <= tree.length <= 40000
0 <= tree[i] < tree.length
这个题目有点不好懂,直接简化一下,题目意思就是求只包含两种元素的最长连续子序列,这样就好理解了;
这个题目其实就是滑动窗口的应用,
滑动窗口就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
其实可以说滑动窗口就是双指针的一种,但是操作起来像一个窗口在移动,所以就叫滑动窗口;
滑动窗口有很多模板,像这道题目的模板很简单:
求最长子数组长度
最长窗口模板
for(枚举选择) {
右边界
while(不符合条件) {
左边界
}
更新结果
}
这个模板很常见,也是通用性很高的,可以记住;
这个题目其实可以用哈希表来做篮子basket,记录不同果树的水果数量,操作起来也更简单
代码有详细注释,代码如下:
class Solution {
public:
int totalFruit(vector<int>& fruits) {
//定义一个哈希表作为篮子,记录每种类型水果的个数
unordered_map<int, int> basket;
//begin是窗口左边界
int begin = 0, ans = 0;
//end是窗口右边界,遍历所有果树
for (int end = 0; end < fruits.size(); ++end) {
//记录每种水果个数
basket[fruits[end]]++;
//如果当前篮子已经有两种以上水果,则不符合题意,需要减去一种水果
while (basket.size() > 2) {
//将窗口左边界(即第一种水果)逐渐向右移
basket[fruits[begin]]--;
//当第一种水果已经删除完了,这时就把这种水果从篮子里移除
//让篮子里只有两种水果
if (basket[fruits[begin]] == 0)
basket.erase(fruits[begin]);
//窗口左边界不断右移更新
begin++;
}
//取最大的情况
ans = max(ans, end - begin + 1);
}
return ans;
}
};