目录
一:题目链接
题目给出的数组元素大小是水果的种类,再把题目理解综合起来就是在给定的水果序列中,找出最多包含 2 种水果的最长连续子序列的长度。
二:题目思路
方法一:
首先,我们可以通过暴力枚举 + 双指针 + a 记录当前水果的种类 的方式,先定义指针 left 和 right 在数组起始的位置,left 先固定,right 往后走,遇到不同元素大小时 a++,遇到相同元素大小时不用管,直到 a == 3 的时候,记录当前子数组序列长度,left 再 往后走,right 回到 left 的位置继续上述流程,直到 left 到达数组末尾。返回得到最大的子数组长度即可。
对于上述的算法,我们可以优化一下。
方法二:
可以使用哈希表来记录当前水果的种类和数量,但是题目给出的 水果种类 数据范围 不超过 10^5 ,所以我们也可以创建一个数组 f 模拟哈希表,数组下标表示水果种类,下标对应的元素大小表示该种类水果的数量。(亲测后者方法通过时长比前者短)。 再定义一个 kinds 记录当前篮子含有的水果种类,len 记录采摘水果的数量,定义指针 left 和 right 在数组起始的位置。( fruits 是题目给出的水果数组)。
首先,left 先固定,right 往后走,如果当前的 f [ fruits[ right ] ] == 0,证明当前篮子里还没有这种类型的水果,此时 kinds ++,并且 f [ fruits[ right ] ] ++,len 不断更新采摘水果的数量,right 不断重复此操作。直到 kinds == 3。如图:

现在,就要移动 left 了,应该怎么移动呢?答案是一直移动直到 kinds == 2 时停止,此时 left 位置是:

因为 right 当前的位置(包含right)已经超过 2 种水果了,那么,必须保证 right 前面只有一种水果 left 才能移动。所以,此时 right 继续重复上述的移动过程,直到 right 走到水果数组 fruits 结尾位置结束。返回过程中 len 记录的最大的长度。
三:代码实现
//使用数组下标模拟水果种类,元素大小表示该种类水果的数量
int n = fruits.length;
int[] f = new int[n];
//记录当前水果种类
int kinds = 0;
//记录采摘水果的数量
int len = 0;
int left = 0;
for(int right = 0;right < n;right++) {
//当前水果的种类
int k = fruits[right];
if(f[k] == 0) {
kinds++;
}
f[k]++; //进窗口
while(kinds > 2) {
//left 位置的水果种类
int a = fruits[left];
f[a]--;
if(f[a] == 0) {
kinds--;
}
left++;
}
//更新采摘水果数量
len = Math.max(len,right - left + 1);
}
return len;
374

被折叠的 条评论
为什么被折叠?



