C++实现LeetCode(904.水果装入果篮)
[LeetCode] 904. Fruit Into Baskets 水果装入果篮
In a row of trees, the `i`-th tree produces fruit with type `tree[i]`.
You start at any tree of your choice, then repeatedly perform the following steps:
- Add one piece of fruit from this tree to your baskets.If you cannot, stop.
- Move to the next tree to the right of the current tree.If there is no tree to the right, stop.
You have two baskets, and each basket can carry any quantity of fruit, but you want each basket to only carry one type of fruit each.
What is the total amount of fruit you can collect with this procedure?
Example 1:
Input: [1,2,1]Example 2:
Output: 3
Explanation: We can collect [1,2,1].
Input: [0,1,2,2]Example 3:
Output: 3
Explanation: We can collect [1,2,2]. If we started at the first tree, we would only collect [0, 1].
Input: [1,2,3,2,2]Example 4:
Output: 4
Explanation: We can collect [2,3,2,2]. If we started at the first tree, we would only collect [1, 2].
Input: [3,3,3,1,2,1,1,2,3,3,4]Note:
Output: 5
Explanation: We can collect [1,2,1,1,2]. If we started at the first tree or the eighth tree, we would only collect 4 fruits.
- 1 <= tree.length <= 40000
- 0 <= tree[i] < tree.length
解法一:
class Solution {public:int totalFruit(vector& tree) {int res = 0, start = 0, n = tree.size(); unordered_map fruitCnt; for (int i = 0; i < n; ++i) {++fruitCnt[tree[i]]; while (fruitCnt.size() > 2) {if (--fruitCnt[tree[start]] == 0) {fruitCnt.erase(tree[start]); }++start; }res = max(res, i - start + 1); }return res; }};
我们除了用 HashMap 来映射字符出现的个数,我们还可以映射每个数字最新的坐标,比如题目中的例子 [0,1,2,2],遇到第一个0,映射其坐标0,遇到1,映射其坐标1,当遇到2时,映射其坐标2,每次我们都判断当前 HashMap 中的映射数,如果大于2的时候,那么需要删掉一个映射,我们还是从 start=0 时开始向右找,看每个字符在 HashMap 中的映射值是否等于当前坐标 start,比如0,HashMap 此时映射值为0,等于 left 的0,那么我们把0删掉,start 自增1,再更新结果,以此类推直至遍历完整个数组,参见代码如下:
解法二:
class Solution {public:int totalFruit(vector& tree) {int res = 0, start = 0, n = tree.size(); unordered_map fruitPos; for (int i = 0; i < n; ++i) {fruitPos[tree[i]] = i; while (fruitPos.size() > 2) {if (fruitPos[tree[start]] == start) {fruitPos.erase(tree[start]); }++start; }res = max(res, i - start + 1); }return res; }};
后来又在网上看到了一种解法,这种解法是维护一个滑动窗口 sliding window,指针 left 指向起始位置,right 指向 window 的最后一个位置,用于定位 left 的下一个跳转位置,思路如下:
- 若当前字符和前一个字符相同,继续循环。
- 若不同,看当前字符和 right 指的字符是否相同:
- 若相同,left 不变,右边跳到 i - 1。
- 若不同,更新结果,left 变为 right+1,right 变为 i - 1。
- 若相同,left 不变,右边跳到 i - 1。
另外需要说明的是这种解法仅适用于于不同字符数为2个的情况,如果为k个的话,还是需要用上面两种解法。
解法三:
class Solution {public:int totalFruit(vector& tree) {int res = 0, left = 0, right = -1, n = tree.size(); for (int i = 1; i < n; ++i) {if (tree[i] == tree[i - 1]) continue; if (right >= 0 && tree[right] != tree[i]) {res = max(res, i - left); left = right + 1; }right = i - 1; }return max(n - left, res); }};
还有一种不使用 HashMap 的解法,这里我们使用若干个变量,其中 cur 为当前最长子数组的长度,a和b为当前候选的两个不同的水果种类,cntB 为水果b的连续个数。我们遍历所有数字,假如遇到的水果种类是a和b中的任意一个,那么 cur 可以自增1,否则 cntB 自增1,因为若是新水果种类的话,默认已经将a种类淘汰了,此时候选水果由类型b和这个新类型水果构成,所以当前长度是 cntB+1。然后再来更新 cntB,假如当前水果种类是b的话,cntB 自增1,否则重置为1,因为 cntB 统计的就是水果种类b的连续个数。然后再来判断,若当前种类不是b,则此时a赋值为b, b赋值为新种类。最后不要忘了用 cur 来更新结果 res,参见代码如下:
解法四:
class Solution {public:int totalFruit(vector& tree) {int res = 0, cur = 0, cntB = 0, a = 0, b = 0; for (int fruit : tree) {cur = (fruit == a || fruit == b) ? cur + 1 : cntB + 1; cntB = (fruit == b) ? cntB + 1 : 1; if (b != fruit) {a = b; b = fruit; }res = max(res, cur); }return res; }};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/904
参考资料:
https://leetcode.com/problems/fruit-into-baskets/
https://leetcode.com/problems/fruit-into-baskets/discuss/170740/Sliding-Window-for-K-Elements
https://leetcode.com/problems/fruit-into-baskets/discuss/170745/Problem%3A-Longest-Subarray-With-2-Elements
https://leetcode.com/problems/fruit-into-baskets/discuss/170808/Java-Longest-Subarray-with-atmost-2-Distinct-elements
到此这篇关于C++实现LeetCode(904.水果装入果篮)的文章就介绍到这了,更多相关C++实现水果装入果篮内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
推荐阅读
- 关于QueryWrapper|关于QueryWrapper,实现MybatisPlus多表关联查询方式
- MybatisPlus使用queryWrapper如何实现复杂查询
- python学习之|python学习之 实现QQ自动发送消息
- 孩子不是实现父母欲望的工具——林哈夫
- opencv|opencv C++模板匹配的简单实现
- Node.js中readline模块实现终端输入
- 【Leetcode/Python】001-Two|【Leetcode/Python】001-Two Sum
- java中如何实现重建二叉树
- leetcode|leetcode 92. 反转链表 II
- 人脸识别|【人脸识别系列】| 实现自动化妆