904.水果成篮
描述:
在一排树中,第 i 棵树产生 tree[i] 型的水果。 你可以从你选择的任何树开始,然后重复执行以下步骤:
- 把这棵树上的水果放进你的篮子里。如果你做不到,就停下来。
- 移动到当前树右侧的下一棵树。如果右边没有树,就停下来。
请注意,在选择一颗树后,你没有任何选择:你必须执行步骤 1,然后执行步骤 2,然后返回步骤 1,然后执行步骤 2,依此类推,直至停止。
你有两个篮子,每个篮子可以携带任何数量的水果,但你希望每个篮子只携带一种类型的水果。
用这个程序你能收集的水果树的最大总量是多少?
示例 1:
输入:[1,2,1] 输出:3 解释:我们可以收集 [1,2,1]。 示例 2:
输入:[0,1,2,2] 输出:3 解释:我们可以收集 [1,2,2] 如果我们从第一棵树开始,我们将只能收集到 [0, 1]。
- 这个题目描述的比较迷, 主要看题目讲述的两个步骤, 和示例, 可以分析出题目要求, 也即在一个数组中, 找出一个子数组, 这个子数组只能含有两个元素, 需要返回找到的最长的子数组的长度.
思路:
-
求子数组, 一般可以处理为滑动窗口法, 即双指针法, 这里我看到了LeetCode的一个题解所说的滑动窗口题目的一个模板, 比较有意义, 在这里引用一下: 求最长子数组长度,直滑动窗口模板。
最长窗口模板(引用链接)
for(枚举选择) 右边界 while(不符合条件) 左边界 更新结果
代码:
/*
* @lc app=leetcode.cn id=904 lang=cpp
*
* [904] 水果成篮
*/
// @lc code=start
class Solution {
public:
int totalFruit(vector<int>& fruits) {
unordered_map<int, int> window;
int res = 0;
for (int left = 0, right = 0; right < fruits.size(); right++) {
window[fruits[right]]++;
while (window.size() > 2) {
window[fruits[left]]--;
if (window[fruits[left]] == 0) {
window.erase(fruits[left]);
}
left++;
}
res = max(res, right - left + 1);
}
return res;
}
};
- 时间复杂度:O(N),其中 N 是
tree的长度。- 空间复杂度:O(N)。
- 这里使用到了C++的STL标准库中的“无序map容器”, 上述代码中14行:
window[fruits[right]]++;可直接将window赋值, 其中, fruits[right]为key, “++”操作后, key对应的值为加一, 初始值为0.