Skip to main content

Command Palette

Search for a command to run...

Solving Leetcode Interviews in Seconds with AI: Find the Maximum Number of Fruits Collected

Updated
6 min read

Introduction

In this blog post, we will explore how to solve the LeetCode problem "3363" using AI. LeetCode is a popular platform for preparing for coding interviews, and with the help of AI tools like Chatmagic, we can generate solutions quickly and efficiently - helping you pass the interviews and get the job offer without having to study for months.

Problem Statement

There is a game dungeon comprised of n x n rooms arranged in a grid. You are given a 2D array fruits of size n x n, where fruits[i][j] represents the number of fruits in the room (i, j). Three children will play in the game dungeon, with initial positions at the corner rooms (0, 0), (0, n - 1), and (n - 1, 0). The children will make exactly n - 1 moves according to the following rules to reach the room (n - 1, n - 1): The child starting from (0, 0) must move from their current room (i, j) to one of the rooms (i + 1, j + 1), (i + 1, j), and (i, j + 1) if the target room exists. The child starting from (0, n - 1) must move from their current room (i, j) to one of the rooms (i + 1, j - 1), (i + 1, j), and (i + 1, j + 1) if the target room exists. The child starting from (n - 1, 0) must move from their current room (i, j) to one of the rooms (i - 1, j + 1), (i, j + 1), and (i + 1, j + 1) if the target room exists. When a child enters a room, they will collect all the fruits there. If two or more children enter the same room, only one child will collect the fruits, and the room will be emptied after they leave. Return the maximum number of fruits the children can collect from the dungeon. Example 1: Input: fruits = [[1,2,3,4],[5,6,8,7],[9,10,11,12],[13,14,15,16]] Output: 100 Explanation: In this example: The 1st child (green) moves on the path (0,0) -> (1,1) -> (2,2) -> (3, 3). The 2nd child (red) moves on the path (0,3) -> (1,2) -> (2,3) -> (3, 3). The 3rd child (blue) moves on the path (3,0) -> (3,1) -> (3,2) -> (3, 3). In total they collect 1 + 6 + 11 + 16 + 4 + 8 + 12 + 13 + 14 + 15 = 100 fruits. Example 2: Input: fruits = [[1,1],[1,1]] Output: 4 Explanation: In this example: The 1st child moves on the path (0,0) -> (1,1). The 2nd child moves on the path (0,1) -> (1,1). The 3rd child moves on the path (1,0) -> (1,1). In total they collect 1 + 1 + 1 + 1 = 4 fruits. Constraints: 2 <= n == fruits.length == fruits[i].length <= 1000 0 <= fruits[i][j] <= 1000

Explanation

Here's the breakdown of the approach, complexities, and the Python code for the problem:

  • High-Level Approach:

    • Dynamic Programming: Use dynamic programming to store the maximum fruits collected by each child at each possible cell they can reach. The state will be dp[child_id][row][col] representing the maximum fruits child child_id can collect ending at position (row, col).
    • Iterative Calculation: Iterate through the grid, calculating the maximum fruits for each child at each cell based on the maximum fruits from the possible previous cells, as dictated by the movement rules. Handle the first cell for each child separately.
    • Collision Handling: When multiple children reach the same cell, choose only one child to collect the fruits at that cell in the current state. The overall algorithm implicitly searches for the best possible choice.
  • Complexity:

    • Runtime Complexity: O(n3), where n is the size of the grid. This is due to the three nested loops in the DP calculation (one for each child, and then iterations over rows and cols).
    • Storage Complexity: O(n2), due to the three DP tables we use, each of size n x n.

Code

    def max_fruits_collected(fruits):
    """
    Calculates the maximum number of fruits three children can collect in a dungeon.

    Args:
        fruits: A 2D list representing the number of fruits in each room.

    Returns:
        The maximum number of fruits the children can collect.
    """

    n = len(fruits)

    # Initialize DP tables for each child
    dp1 = [[0] * n for _ in range(n)]  # Child 1 (0, 0)
    dp2 = [[0] * n for _ in range(n)]  # Child 2 (0, n-1)
    dp3 = [[0] * n for _ in range(n)]  # Child 3 (n-1, 0)

    # Initialize starting positions
    dp1[0][0] = fruits[0][0]
    dp2[0][n - 1] = fruits[0][n - 1]
    dp3[n - 1][0] = fruits[n - 1][0]

    # Iterate through the grid
    for i in range(n):
        for j in range(n):
            # Skip the first rooms which are initialized already
            if (i == 0 and j == 0) or (i == 0 and j == n - 1) or (i == n - 1 and j == 0):
                continue

            # Calculate possible paths for each child
            # Child 1
            options1 = []
            if i > 0 and j > 0:
                options1.append(dp1[i - 1][j - 1])
            if i > 0:
                options1.append(dp1[i - 1][j])
            if j > 0:
                options1.append(dp1[i][j - 1])

            # Child 2
            options2 = []
            if i > 0 and j > 0:
                options2.append(dp2[i - 1][j - 1])
            if i > 0 and j < n - 1:
                options2.append(dp2[i - 1][j + 1])
            if i > 0:
                options2.append(dp2[i - 1][j])

            # Child 3
            options3 = []
            if i < n - 1 and j > 0:
                options3.append(dp3[i + 1][j - 1])
            if j > 0:
                options3.append(dp3[i][j - 1])
            if i < n - 1:
                options3.append(dp3[i + 1][j])

            # Calculate maximum fruits considering collisions
            max_fruits = 0
            # Iterate through all possible "who picks up the fruit" scenarios:
            for c1 in ([0] if not options1 else [max(options1)]):
                for c2 in ([0] if not options2 else [max(options2)]):
                    for c3 in ([0] if not options3 else [max(options3)]):

                        if c1 > 0 or c2 > 0 or c3 > 0:
                            # At most one child takes the fruit
                            if c1 >= c2 and c1 >= c3 and c1 > 0:
                                current_fruits = c1 + fruits[i][j] if (i != n-1 or j != n-1) else c1
                            elif c2 >= c1 and c2 >= c3 and c2 > 0 :
                                current_fruits = c2 + fruits[i][j] if (i != n-1 or j != n-1) else c2
                            elif c3 >= c1 and c3 >= c2 and c3 > 0:
                                current_fruits = c3 + fruits[i][j] if (i != n-1 or j != n-1) else c3
                            else: # no one pick up
                                current_fruits = c1 + c2 + c3
                        else:
                            current_fruits = c1 + c2 + c3


                        max_fruits = max(max_fruits, current_fruits)

            if len(options1) > 0:
                dp1[i][j] = max(options1) + (fruits[i][j] if dp1[i][j] == 0 else 0)

            if len(options2) > 0:
                dp2[i][j] = max(options2) + (fruits[i][j] if dp2[i][j] == 0 else 0)

            if len(options3) > 0:
                dp3[i][j] = max(options3) + (fruits[i][j] if dp3[i][j] == 0 else 0)


    # Calculate the total maximum fruits collected at the final room (n-1, n-1)
    return dp1[n - 1][n - 1] + dp2[n - 1][n - 1] + dp3[n - 1][n - 1] - 2 * fruits[n - 1][n - 1]

More from this blog

C

Chatmagic blog

2894 posts