问题描述:
在一排树中,第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]。
提示:
1 <= tree.length <= 40000
0 <= tree[i] < tree.length
问题分析:
先看看题目,要注意的几点,第一,tree[i]
表示水果的类型,不是水果的个数哦。第二,两个篮子,只能获取两种水果,第三,求收集水果的总量,感觉可以简单理解为采摘树的棵树。现在就可以理解为,就是,获取 tree[]
其中的一个最长子序列,而且这个子序列,只有两种水果。
解题思路:
(1)使用双指针法或者是滑动窗口法,遍历整个 tree[]
,找到一个小区间内只有两个水果,而且,这个区间的长度是所有子区间最长的,即可。
(2)可以使用 cnt = {}
来保存一个区间的元素统计数,用i
表示这个滑动窗口的左端,j
表示换的窗口的右端,j
随着遍历tree[]
一直向右端走。
(3)每次遍历一个元素,就要更新 cnt = {}
并判断长度是否超过了2
,如果超过了,此时就开始处理左端点i
,i
开始向右移动,同时更新 cnt = {}
,直到 cnt = {}
的长度小于等于2
,并更新保留一次最优的结果。依次类推,直到结束。
Python3实现:
class Solution:
def totalFruit(self, tree):
cnt = {}
i = res = 0
for j, v in enumerate(tree):
cnt[v] = cnt.get(v, 0) + 1 # cnt.get(v, 0) 从字典里获取一个数,如果不存在就默认为 0
while len(cnt) > 2: # 如果字典中的元素大于 2
cnt[tree[i]] -= 1
if cnt[tree[i]] == 0:
del cnt[tree[i]]
i += 1
res = max(res, j - i + 1) # 结束一个区间,更新一次最优结果
return res
if __name__ == '__main__':
solu = Solution()
tree = [3, 3, 3, 1, 2, 1, 1, 2, 3, 3, 4]
print(solu.totalFruit(tree))
声明: 总结学习,有问题可以批评指正,大神可以略过哦
题目链接:leetcode-cn.com/problems/fruit-into-baskets/description/
参考链接:leetcode.com/problems/fruit-into-baskets/discuss/170740/C%2B%2BPython-Sliding-Window