leetcode刷题系列
在一排树中,第 i 棵树产生 fruits[i] 型的水果。
可以从选择的任何树开始,然后重复执行以下步骤:
1.把这棵树上的水果放进你的篮子里。如果你做不到,就停下来。
2.移动到当前树右侧的下一棵树。如果右边没有树,就停下来。
请注意,在选择一颗树后,你没有任何选择:你必须执行步骤 1,然后执行步骤 2,然后返回步骤 1,然后执行步骤 2,依此类推,直至停止。
有两个篮子,每个篮子可以携带任何数量的水果,但每个篮子只能携带一种类型的水果。
求解收集的水果的最大总量是多少?
解析:
此题可以用滑动窗口方法来解决。相当于找一个数组中最长的子数组,这个子数组中最多只能有两种元素。
问题的重点在于如何确定新窗口的左边位置。
设水果篮中一共有两种水果fruit1和fruit2,窗口最左边位置为l,最右边位置为r。篮子中的水果数可以用(r-l+1)表示。
r每次循环中增加1,若此时fruits[r]与fruit1或者fruit2相等,水果篮中水果数增加1,否则的话,由于遇到了水果篮中不存在的水果,就要更新窗口最左边的位置。而窗口最左边的位置,实际上就是从r开始从右往左数,直到遇到一个与fruits[r-1]不同的数(假设其下标为n),则窗口最左边的位置便是(n+1),例子如下:
int[] fruits={7,8,7,7,7,7,9,9}
以上fruits数组中,假设现在r指向了9号水果第一次出现的位置即r=6,fruits[r]=9
此时fruit1=7,fruit2=8,fruits[r]与fruit1和fruit2都不一样,此时就要更新窗口最左边的位置,
由于r左边是一串7的子序列,我们便要找到这串序列里最左边的那个位置作为新窗口的最左边
此例子中7序列最左边的那个7所在下标为2,因此让l=2
代码中使用了一个变量index标记每次窗口更新时,l的位置
完全代码如下:
public static int totalFruit(int[] fruits) {
int res=0;
int l=0;//窗户最左边,初始位置为0
int r=0;//窗户最右边,初始位置为0
int index=0;//index为要产生新窗口时,左窗口的位置
int fruit1=fruits[0];//第一种水果
//先找到第二种水果所在的初始位置
while (fruits[r]==fruits[l]){
r++;
//若数组fruits中只有一种水果,便直接放回水果的总数
if(r==fruits.length-1) return fruits.length;
}
int fruit2=fruits[r];//第二种水果
for (; r <fruits.length ; r++) {
if(fruits[r]!=fruit2 && fruits[r]!=fruit1){
fruit1=fruits[index];
fruit2=fruits[r];
l=index;
}
if(fruits[index]!=fruits[r]) index=r;
res=Math.max(r-l+1,res);
}
return res;
}