0. 题干
leetcode 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]。
示例 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
注意这里题目稍微有点难理解,比如那个[0,1,2,2]的例子,tree[0]=0、tree[1]=1、tree[2]=2、tree[3]=2,因为只有两个篮子,一个篮子只能存一种水果,所以要么存0、1;要么存1、2、2;题干说的两个步骤,停下来的意思是程序直接结束了
1. 代码如下,写了很详细的注释
class Solution{
public:
int totalFruit(vector<int>& tree) {
int left=0,mid=0,right=0;
int len=tree.size();
int sum=0; //统计最终的返回值
if (len<2) //数组长度小于2,还解个锤子,直接返回数组长度
return len;
for (; right<len-1; right++) // 找到第二种树的位置
if( tree[right]!= tree[right+1] ) //此时的right+1值即为第二种树开始位置
break;
mid= ++right; //此时的mid存储第二种树的位置
//运行之后,right的值默认为第二种树开始的位置
//以下for循环为重点处理
for (; right < len; right++){
if ( tree[right]!= tree[mid] && tree[right]!= tree[left] ) {
//找到第三种树
sum = max(sum, right-left); //每次运行之后的right即为下一种树的开头,
//所以直接减去left即可.
mid = right; //存储此时第三种树的位置
left= right -1; //既然之前找到了第三种树,此时减一即为第二种树的位置
while ( tree[left] == tree[left-1] )
//通过这种方式找到前面一种树第一次出现的位置
left--;
}
}
right--; //for循环运行之后,right=len,减一避免下面数组越界
if (left==0)
return len; //如果left=0,即,left[2]=left[1],left[1]=left[0]等.
//表明树的种类一定是小于三种的,因为如果树的种类大于三种,
//由于while ( tree[left] == tree[left-1] )
//left一定会卡在中间某个位置,不会在0
if (tree[right] == tree[mid] || tree[right] == tree[left])
//若数组的最后一位不是新的树,即不经过重点for循环sum处理,for (; right < len; right++){
//要更新sum值
return max(sum, right-left+1); //+1的原因是right--,
//此时right不是同类树的下一个下标,而是同类树的最后一个下标,所以要+1
return sum;
}
};
OVER! 感谢阅读。