你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。
你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。
示例 1:
输入:fruits = [1,2,1]
输出:3
解释:可以采摘全部 3 棵树。
示例 2:
输入:fruits = [0,1,2,2]
输出:3
解释:可以采摘 [1,2,2] 这三棵树。 如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。
示例 3:
输入:fruits = [1,2,3,2,2]
输出:4
解释:可以采摘 [2,3,2,2] 这四棵树。 如果从第一棵树开始采摘,则只能采摘 [1,2] 这两棵树。
示例 4:
输入:fruits = [3,3,3,1,2,1,1,2,3,3,4]
输出:5
解释:可以采摘 [1,2,1,1,2] 这五棵树。
提示:
我的想法:
最开始想着暴力输出,最后一个测试案例没过,就那个数组前面一堆的 0 的那个测试案例。
# Python3
class Solution:
def totalFruit(self, fruits: List[int]) -> int:
left = right = 0
timemax = 0
fruitlist = list()
while right < len(fruits):
if fruits[right] not in fruitlist:
fruitlist.append(fruits[right])
while 1:
if len(set(fruitlist)) > 2:
fruitlist.pop(0)
else:
break
else:
fruitlist.append(fruits[right])
timemax = max(timemax, len(fruitlist))
right += 1
return timemax
后来想着滑动窗口和双指针:
第一种:
left = right = 0,fruitlist 用来收集水果种类
[1,0,1,4,1,4,1,2,3]
右移 right
timemax = max(timemax, right-left + 1) = 3
[1,0,1,4,1,4,1,2,3]
当 right 指向 4 的时候,fruitlist 长度为3,让 left 指向 fruitlist 的第二种,即 0 。
[1,0,1,4,1,4,1,2,3]
取 fruitlist 的第一种,即 1。如果 1 和 right 前一个值相同的话,即 1 和 1 相同。
取 fruitlist 的第二种,即0。如果 0 在 fruits[left:right] 中,left 右移,将 0 从 fruitlist 删去。fruitlist 里为 1 和 4。
[1,0,1,4,1,4,1,2,3]
右移 right ,之后同理。
第二种:
left = right = 0,fruitlist 用来收集水果种类
[3,3,3,1,2,1,1,2,3,3,4]
右移 right
timemax = max(timemax, right-left + 1) = 4
[3,3,3,1,2,1,1,2,3,3,4]
当 right 指向 2 的时候,fruitlist 长度为 3,让 left 指向 fruitlist 的第二种,即 1 。
[3,3,3,1,2,1,1,2,3,3,4]
取 fruitlist 的第一种,即 3。如果 3 和 right 前一个值不同的话,即 3 和 1 不同。
如果 3 在 fruits[left:right] 中,left 右移。这里不在,将 3 从 fruitlist 删去。fruitlist 里为 1 和 2。
右移 right
timemax = max(timemax, right-left + 1) = 5
[3,3,3,1,2,1,1,2,3,3,4]
当 right 指向 3 的时候,fruitlist 长度为 3,让 left 指向 fruitlist 的第二种,即 2 。
[3,3,3,1,2,1,1,2,3,3,4]
取 fruitlist 的第一种,即 1。如果 1 和 right 前一个值不同的话,即 1 和 2 不同。
如果 1 在 fruits[left:right] 中,left 右移。
[3,3,3,1,2,1,1,2,3,3,4]
将 1 从fruitlist 中删去
class Solution:
def totalFruit(self, fruits: List[int]) -> int:
left = right = 0 # left、right先都指向列表第一位
timemax = 0 # 收集的水果的最大数目
fruitlist = list() # 收集水果种类的列表
n = len(fruits)
while right < n:
if fruits[right] not in fruitlist:
fruitlist.append(fruits[right])
if len(fruitlist) <= 2:
timemax = max(timemax, right-left + 1)
elif len(fruitlist) > 2:
left = left + fruits[left:right].index(fruitlist[1])
string = fruitlist[0]
if string != fruits[right - 1]:
while string in fruits[left:right]:
left += 1
fruitlist.pop(0)
else:
string = fruitlist[1]
while string in fruits[left:right]:
left += 1
fruitlist.pop(1)
right += 1
return timemax
class Solution:
def totalFruit(self, fruits: List[int]) -> int:
cnt = Counter()
left = ans = 0
for right, x in enumerate(fruits):
cnt[x] += 1
while len(cnt) > 2:
cnt[fruits[left]] -= 1
if cnt[fruits[left]] == 0:
cnt.pop(fruits[left])
left += 1
ans = max(ans, right - left + 1)
return ans
作者:力扣官方题解
链接:https://leetcode.cn/problems/fruit-into-baskets/solutions/1893352/shui-guo-cheng-lan-by-leetcode-solution-1uyu/
C++:
class Solution {
public:
int totalFruit(vector<int>& fruits) {
int n = fruits.size();
unordered_map<int, int> cnt;
int left = 0, ans = 0;
for (int right = 0; right < n; ++right) {
++cnt[fruits[right]];
while (cnt.size() > 2) {
auto it = cnt.find(fruits[left]);
--it->second;
if (it->second == 0) {
cnt.erase(it);
}
++left;
}
ans = max(ans, right - left + 1);
}
return ans;
}
};
C:
#define MAX(a, b) ((a) > (b) ? (a) : (b))
typedef struct {
int key;
int val;
UT_hash_handle hh;
} HashItem;
HashItem *hashFindItem(HashItem **obj, int key) {
HashItem *pEntry = NULL;
HASH_FIND_INT(*obj, &key, pEntry);
return pEntry;
}
bool hashAddItem(HashItem **obj, int key, int val) {
if (hashFindItem(obj, key)) {
return false;
}
HashItem *pEntry = (HashItem *)malloc(sizeof(HashItem));
pEntry->key = key;
pEntry->val = val;
HASH_ADD_INT(*obj, key, pEntry);
return true;
}
bool hashSetItem(HashItem **obj, int key, int val) {
HashItem *pEntry = hashFindItem(obj, key);
if (!pEntry) {
hashAddItem(obj, key, val);
} else {
pEntry->val = val;
}
return true;
}
int hashGetItem(HashItem **obj, int key, int defaultVal) {
HashItem *pEntry = hashFindItem(obj, key);
if (!pEntry) {
return defaultVal;
}
return pEntry->val;
}
void hashFree(HashItem **obj) {
HashItem *curr = NULL, *tmp = NULL;
HASH_ITER(hh, *obj, curr, tmp) {
HASH_DEL(*obj, curr);
free(curr);
}
}
int totalFruit(int* fruits, int fruitsSize){
HashItem *cnt = NULL;
int left = 0, ans = 0;
for (int right = 0; right < fruitsSize; ++right) {
hashSetItem(&cnt, fruits[right], hashGetItem(&cnt, fruits[right], 0) + 1);
while (HASH_COUNT(cnt) > 2) {
HashItem *pEntry = hashFindItem(&cnt, fruits[left]);
pEntry->val--;
if (pEntry->val == 0) {
HASH_DEL(cnt, pEntry);
free(pEntry);
}
++left;
}
ans = MAX(ans, right - left + 1);
}
hashFree(&cnt);
return ans;
}