3 minute read

Problem Statement

leetcode problem link

Sliding window Approach [Accepted]

from collections import OrderedDict
class Solution:
    def totalFruit(self, fruits: List[int]) -> int:
        res = 0
        left, right = 0, 0
        N = len(fruits)
        picked = defaultdict(int)
        for right in range(N):
            fruit = fruits[right]
            picked[fruit] += 1
            while left < N and len(picked) > 2:
                left_most_fruit = fruits[left]
                picked[left_most_fruit] -= 1
                if picked[left_most_fruit] == 0:
                    del picked[left_most_fruit]
                left += 1
            if len(picked) <= 2:
                res = max(res, right - left + 1)
        return res

Editorial

Approach 1: Brute Force

class Solution:
    def totalFruit(self, fruits: List[int]) -> int:
        # Maximum number of fruits we can pick
        max_picked = 0

        # Iterate over all subarrays: left index left, right index right.
        for left in range(len(fruits)):
            for right in range(left, len(fruits)):
                # Use a set to count the type of fruits.
                basket = set()

                # Iterate over the current subarray (left, right).
                for current_index in range(left, right + 1):
                    basket.add(fruits[current_index])

                # If the number of types of fruits in this subarray (types of fruits)
                # is no larger than 2, this is a valid subarray, update 'max_picked'.
                if len(basket) <= 2:
                    max_picked = max(max_picked, right - left + 1)

        # Return 'max_picked' as the maximum length (maximum number of fruits we can pick).
        return max_picked

Approach 2: Optimized Brute Force

class Solution:
    def totalFruit(self, fruits: List[int]) -> int:
        # Maximum number of fruits we can pick
        max_picked = 0

        # Iterate over the left index left of subarrays.
        for left in range(len(fruits)):
            # Empty set to count the type of fruits.
            basket = set()
            right = left

            # Iterate over the right index right of subarrays.
            while right < len(fruits):
                # Early stop. If adding this fruit makes 3 types of fruit,
                # we should stop the inner loop.
                if fruits[right] not in basket and len(basket) == 2:
                    break

                # Otherwise, update the number of this fruit.
                basket.add(fruits[right])
                right += 1

            # Update max_picked
            max_picked = max(max_picked, right - left)

        # Return maxPicked as the maximum length of valid subarray.
        # (maximum number of fruits we can pick).
        return max_picked

Approach 3: Sliding Window

class Solution:
    def totalFruit(self, fruits: List[int]) -> int:
        # Hash map 'basket' to store the types of fruits.
        basket = {}
        left = 0

        # Add fruit from the right index (right) of the window.
        for right, fruit in enumerate(fruits):
            basket[fruit] = basket.get(fruit, 0) + 1

            # If the current window has more than 2 types of fruit,
            # we remove one fruit from the left index (left) of the window.
            if len(basket) > 2:
                basket[fruits[left]] -= 1

                # If the number of fruits[left] is 0, remove it from the basket.
                if basket[fruits[left]] == 0:
                    del basket[fruits[left]]
                left += 1

        # Once we finish the iteration, the indexes left and right
        # stands for the longest valid subarray we encountered.
        return right - left + 1

Approach 4: Sliding Window II

class Solution:
    def totalFruit(self, fruits: List[int]) -> int:
        # We use a hash map 'basket' to store the number of each type of fruit.
        basket = {}
        max_picked = 0
        left = 0

        # Add fruit from the right index (right) of the window.
        for right in range(len(fruits)):
            basket[fruits[right]] = basket.get(fruits[right], 0) + 1

            # If the current window has more than 2 types of fruit,
            # we remove fruit from the left index (left) of the window,
            # until the window has only 2 types of fruit.
            while len(basket) > 2:
                basket[fruits[left]] -= 1
                if basket[fruits[left]] == 0:
                    del basket[fruits[left]]
                left += 1

            # Update max_picked.
            max_picked = max(max_picked, right - left + 1)

        # Return max_picked as the maximum number of fruits we can collect.
        return max_picked