题目
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.
Note that you do not have any choice after the initial choice of starting tree: you must perform step 1, then step 2, then back to step 1, then step 2, and so on until you 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?
示例
Input: [3,3,3,1,2,1,1,2,3,3,4]
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.
解析
数组中的每一个元素代表一种类型的水果,只有两个篮子,一个篮子只能放一种类型的水果,所以可以将题意理解为求一个最长的连续子序列,这个子序列中最多包含两个不同的数据。
这种问题经典的解法是sliding window的解法,我们可以定义一个窗口,start为窗口的起始位置,i为当前窗口结束位置,窗口大小即为最多可以采摘的水果个数。
然后我们定义一个map,存放当前窗口中每个元素出现的次数,当map中出现两个以上元素时开始移动窗口,否则start不变,i++,扩大窗口。
以示例输入为例进行简单解析:
i=0, { map[3]=1 }, start=0
i=1, { map[3]=2 }, start=0
i=2, { map[3]=3 }, start=0
i=3, { map[3]=3, map[1]=1 }, start=0
i=4, { map[3]=2, map[1]=1, map[2]=1 }, start=1 //此时map中出现3,1,2三个元素,所以开始平移窗口。
i=5, { map[3]=1, map[1]=2, map[2]=1 }, start=2
i=6, { map[1]=3, map[2]=1 }, start=3
i=7, { map[1]=3, map[2]=2 }, start=3
i=8, { map[1]=2, map[2]=2, map[3]=1 }, start=4
i=9, { map[1]=1, map[2]=2, map[3]=2 }, start=5
i=10, { map[1]=1, map[2]=2, map[3]=2 }, start=6
算法
int totalFruit(vector<int>& tree) {
int start = 0;
unordered_map<int,int> m;
int i = 0;
for(i=0;i<tree.size();i++){
m[tree[i]]++;
if(m.size()>2){ //if there is more than two elements in map, begin sliding window
m[tree[start]]--;
if(m[tree[start]]==0) m.erase(tree[start]);
start++;
}
}
return i-start;
}