Maximum Score Using Neighbor Products

Last Updated : 2 Sep, 2026

Given an array arr[] of positive integers, repeatedly remove one element until the array becomes empty. 

The process of removal is as follows, 

  • When removing an element, add the product of the element and its current left and right neighbors to the score.
  • If the element is at either end of the current array, assume its missing neighbor has value 1.
  • After removing an element, the remaining elements become adjacent.

Return the maximum possible score that can be obtained.

Examples:

Input: arr[] = [5, 10]
Output: 60
Explanation: Remove 5: 1 * 5 * 10 = 50
Remove 10: 1 * 10 * 1 = 10
Total score = 50 + 10 = 60

Input: arr[] = [1, 2, 3, 4, 5]
Output: 110
Explanation: Remove 4 first: 3 * 4 * 5 = 60 Array becomes [1, 2, 3, 5].
Remove 3: 2 * 3 * 5 = 30 Array becomes [1, 2, 5].
Remove 2: 1 * 2 * 5 = 10 Array becomes [1, 5].
Remove 1: 1 * 1 * 5 = 5 Array becomes [5]
Remove 5: 1 * 5 * 1 = 5
Total score = 60 + 30 + 10 + 5 + 5 = 110.

Try It Yourself
redirect icon

[Naive Approach] Try Every Possible Removal - O(n × n!) Time and O(n) Space

For every element i, calculate the score obtained by removing it using its left and right neighbors. Then, recursively for the remaining elements and take the maximum of all possible choices.

This gives the recurrence relation:
solve(arr) = max(left × arr[i] × right + solve(remaining array))

Working of Approach:

  • Try each element as the next element to remove.
  • Find its current left and right neighbors; use 1 if a neighbor is missing.
  • Add left * element * right to the current score.
  • Remove the element and recursively solve the remaining array.
  • Restore the element and take the maximum score.
C++
#include <iostream>
#include <vector>
using namespace std;

int solve(vector<int> &arr)
{

    // If no elements are left, no more score can be added.
    if (arr.empty())
        return 0;

    int n = arr.size();
    int ans = 0;

    // Try every element as the next element to remove.
    for (int i = 0; i < n; i++)
    {

        // Find the current left neighbor.
        int left = (i == 0) ? 1 : arr[i - 1];

        // Find the current right neighbor.
        int right = (i == n - 1) ? 1 : arr[i + 1];

        // Calculate the score for removing arr[i].
        int score = left * arr[i] * right;

        // Store the value before removing it.
        int val = arr[i];

        // Remove the current element.
        arr.erase(arr.begin() + i);

        // Recursively find the best score
        // for the remaining elements.
        score += solve(arr);

        // Restore the element for the next choice.
        arr.insert(arr.begin() + i, val);

        // Update the maximum score.
        ans = max(ans, score);
    }

    return ans;
}

int maxProductSum(vector<int> &arr)
{
    return solve(arr);
}

int main()
{

    vector<int> arr = {1, 2, 3, 4, 5};

    cout << maxProductSum(arr) << endl;

    return 0;
}
Java
import java.util.ArrayList;

public class GFG {

    public static int solve(ArrayList<Integer> arr)
    {
        // If no elements are left, no more score can be
        // added.
        if (arr.isEmpty())
            return 0;

        int n = arr.size();
        int ans = 0;

        // Try every element as the next element to remove.
        for (int i = 0; i < n; i++) {

            // Find the current left neighbor.
            int left = (i == 0) ? 1 : arr.get(i - 1);

            // Find the current right neighbor.
            int right = (i == n - 1) ? 1 : arr.get(i + 1);

            // Calculate the score for removing arr[i].
            int score = left * arr.get(i) * right;

            // Store the value before removing it.
            int val = arr.get(i);

            // Remove the current element.
            arr.remove(i);

            // Recursively find the best score for
            // the remaining elements.
            score += solve(arr);

            // Restore the element for the next choice.
            arr.add(i, val);

            // Update the maximum score.
            ans = Math.max(ans, score);
        }

        return ans;
    }

    public static int maxProductSum(int[] arr)
    {
        ArrayList<Integer> list = new ArrayList<>();

        // Convert the array into an ArrayList.
        for (int num : arr)
            list.add(num);

        return solve(list);
    }

    public static void main(String[] args)
    {
        int[] arr = { 1, 2, 3, 4, 5 };

        System.out.println(maxProductSum(arr));
    }
}
Python
def solve(arr):

    # If no elements are left, no more score can be added.
    if not arr:
        return 0

    n = len(arr)
    ans = 0

    # Try every element as the next element to remove.
    for i in range(n):

        # Find the current left neighbor.
        left = 1 if i == 0 else arr[i - 1]

        # Find the current right neighbor.
        right = 1 if i == n - 1 else arr[i + 1]

        # Calculate the score for removing arr[i].
        score = left * arr[i] * right

        # Store the value before removing it.
        val = arr[i]

        # Remove the current element.
        arr.pop(i)

        # Recursively find the best score
        # for the remaining elements.
        score += solve(arr)

        # Restore the element for the next choice.
        arr.insert(i, val)

        # Update the maximum score.
        ans = max(ans, score)

    return ans


def maxProductSum(arr):
    return solve(arr)


if __name__ == '__main__':
    arr = [1, 2, 3, 4, 5]
    print(maxProductSum(arr))
C#
using System;
using System.Collections.Generic;

public class GFG {

    public static int Solve(List<int> arr)
    {
        // If no elements are left, no more score can be
        // added.
        if (arr.Count == 0)
            return 0;

        int n = arr.Count;
        int ans = 0;

        // Try every element as the next element to remove.
        for (int i = 0; i < n; i++) {
            // Find the current left neighbor.
            int left = (i == 0) ? 1 : arr[i - 1];

            // Find the current right neighbor.
            int right = (i == n - 1) ? 1 : arr[i + 1];

            // Calculate the score for removing arr[i].
            int score = left * arr[i] * right;

            // Store the value before removing it.
            int val = arr[i];

            // Remove the current element.
            arr.RemoveAt(i);

            // Recursively find the best score.
            score += Solve(arr);

            // Restore the element for the next choice.
            arr.Insert(i, val);

            // Update the maximum score.
            ans = Math.Max(ans, score);
        }

        return ans;
    }

    public static int maxProductSum(int[] arr)
    {
        List<int> list = new List<int>(arr);
        return Solve(list);
    }

    public static void Main()
    {
        int[] arr = { 1, 2, 3, 4, 5 };

        int result = maxProductSum(arr);

        Console.WriteLine(result);
    }
}
JavaScript
function solve(arr)
{

    // If no elements are left, no more score can be added.
    if (arr.length === 0)
        return 0;

    let n = arr.length;
    let ans = 0;

    // Try every element as the next element to remove.
    for (let i = 0; i < n; i++) {

        // Find the current left neighbor.
        let left = (i === 0) ? 1 : arr[i - 1];

        // Find the current right neighbor.
        let right = (i === n - 1) ? 1 : arr[i + 1];

        // Calculate the score for removing arr[i].
        let score = left * arr[i] * right;

        // Store the value before removing it.
        let val = arr[i];

        // Remove the current element.
        arr.splice(i, 1);

        // Recursively find the best score
        // for the remaining elements.
        score += solve(arr);

        // Restore the element for the next choice.
        arr.splice(i, 0, val);

        // Update the maximum score.
        ans = Math.max(ans, score);
    }

    return ans;
}

function maxProductSum(arr) { return solve(arr); }

// Driver Code
let arr = [ 1, 2, 3, 4, 5 ];
console.log(maxProductSum(arr));

Output
110

[Expected Approach] Using Bottom-Up Interval DP - O(n ^ 3) Time and O(n ^ 2) Space

We use a 2D DP array dp of size (n+2) × (n+2) (as virtual persons with a rating of 1 are also added at both ends of the arr[] to simplify the boundary conditions), where dp[left][right] stores the maximum value obtainable from removing all in the range [left, right].

We initialize all entries in dp to -1 and populate them using memoization as we calculate optimal subproblems.

Working of Approach:

  • Add 1 at both ends of the array to represent missing neighbors.
  • Let dp[left][right] store the maximum score for removing all elements in that interval.
  • Try every last element as the last element removed from the interval.
  • Its score becomes nums[left-1] * nums[last] * nums[right+1].
  • Add the answers of the left and right subintervals and take the maximum.

Let us understand with an example:
Input: arr[] = [1, 2, 3, 4, 5]

  • For single-element intervals, dp[left][right] stores nums[left-1] * nums[left] * nums[right+1].
  • For larger intervals, every element is considered as the last element to remove, and the best left and right subinterval scores are added.
  • For the complete interval [1, 5], choosing 5 as the last element gives the optimal score.
  • The corresponding optimal removal order is 4 -> 3 -> 2 -> 1 -> 5, giving a total score of 110.
  • Hence, dp[1][5] = 110, so the function returns 110.
C++
#include <iostream>
#include <vector>
using namespace std;

int maxProductSum(vector<int> &arr)
{

    int n = arr.size();

    vector<int> nums(n + 2);

    nums[0] = 1;
    nums[n + 1] = 1;

    for (int i = 1; i <= n; i++)
    {
        nums[i] = arr[i - 1];
    }

    vector<vector<int>> dp(n + 2, vector<int>(n + 2, 0));

    // Compute the maximum score for every interval.
    for (int len = 1; len <= n; len++)
    {

        for (int left = 1; left <= n - len + 1; left++)
        {

            int right = left + len - 1;

            // Assume each element is removed last in the interval.
            for (int last = left; last <= right; last++)
            {

                dp[left][right] =
                    max(dp[left][right], dp[left][last - 1] + nums[left - 1] * nums[last] * nums[right + 1] +
                                             dp[last + 1][right]);
            }
        }
    }

    return dp[1][n];
}

int main()
{

    vector<int> arr = {1, 2, 3, 4, 5};

    cout << maxProductSum(arr) << endl;

    return 0;
}
Java
import java.util.Arrays;

public class GFG {

    static int maxProductSum(int[] arr)
    {
        int n = arr.length;

        // Add virtual boundary elements with value 1.
        int[] nums = new int[n + 2];
        Arrays.fill(nums, 0);

        nums[0] = 1;
        nums[n + 1] = 1;

        // Copy the original array.
        for (int i = 1; i <= n; i++) {
            nums[i] = arr[i - 1];
        }

        // dp[left][right] stores the maximum score
        // obtainable from the subarray [left, right].
        int[][] dp = new int[n + 2][n + 2];

        // Consider all possible interval lengths.
        for (int len = 1; len <= n; len++) {

            for (int left = 1; left <= n - len + 1;
                 left++) {
                int right = left + len - 1;

                // Choose each element as the last one
                // to be removed from this interval.
                for (int last = left; last <= right;
                     last++) {

                    dp[left][right] = Math.max(
                        dp[left][right],
                        dp[left][last - 1]
                            + nums[left - 1] * nums[last]
                                  * nums[right + 1]
                            + dp[last + 1][right]);
                }
            }
        }

        return dp[1][n];
    }

    public static void main(String[] args)
    {
        int[] arr = { 1, 2, 3, 4, 5 };

        System.out.println(maxProductSum(arr));
    }
}
Python
def maxProductSum(arr):
    n = len(arr)

    # Add virtual boundary elements with value 1.
    nums = [1] + arr + [1]

    # dp[left][right] stores the maximum score
    # obtainable from the interval [left, right].
    dp = [[0] * (n + 2) for _ in range(n + 2)]

    # Consider intervals of increasing length.
    for length in range(1, n + 1):
        for left in range(1, n - length + 2):
            right = left + length - 1

            # Choose each element as the last element
            # to be removed from this interval.
            for last in range(left, right + 1):
                dp[left][right] = max(
                    dp[left][right],
                    dp[left][last - 1]
                    + nums[left - 1] * nums[last] * nums[right + 1]
                    + dp[last + 1][right]
                )

    return dp[1][n]


if __name__ == '__main__':
    arr = [1, 2, 3, 4, 5]
    print(maxProductSum(arr))
C#
using System;

class GFG {
    static int maxProductSum(int[] arr)
    {
        int n = arr.Length;

        // Add virtual boundary elements with value 1.
        int[] nums = new int[n + 2];
        nums[0] = 1;
        nums[n + 1] = 1;

        // Copy the original array.
        for (int i = 1; i <= n; i++) {
            nums[i] = arr[i - 1];
        }

        // dp[left, right] stores the maximum score
        // obtainable from the interval [left, right].
        int[, ] dp = new int[n + 2, n + 2];

        // Consider intervals of increasing length.
        for (int len = 1; len <= n; len++) {
            for (int left = 1; left <= n - len + 1;
                 left++) {
                int right = left + len - 1;

                // Choose each element as the last element
                // to be removed from this interval.
                for (int last = left; last <= right;
                     last++) {
                    dp[left, right] = Math.Max(
                        dp[left, right],
                        dp[left, last - 1]
                            + nums[left - 1] * nums[last]
                                  * nums[right + 1]
                            + dp[last + 1, right]);
                }
            }
        }

        return dp[1, n];
    }

    static void Main()
    {
        int[] arr = { 1, 2, 3, 4, 5 };

        Console.WriteLine(maxProductSum(arr));
    }
}
JavaScript
function maxProductSum(arr)
{
    let n = arr.length;
    let nums = new Array(n + 2).fill(0);
    nums[0] = 1;
    nums[n + 1] = 1;
    for (let i = 1; i <= n; i++) {
        nums[i] = arr[i - 1];
    }
    let dp = Array.from({length : n + 2},
                        () => Array(n + 2).fill(0));
    for (let len = 1; len <= n; len++) {
        for (let left = 1; left <= n - len + 1; left++) {
            let right = left + len - 1;
            for (let last = left; last <= right; last++) {
                dp[left][right] = Math.max(
                    dp[left][right],
                    dp[left][last - 1]
                        + nums[left - 1] * nums[last]
                              * nums[right + 1]
                        + dp[last + 1][right]);
            }
        }
    }
    return dp[1][n];
}

// Driver Code
let arr = [ 1, 2, 3, 4, 5 ];
console.log(maxProductSum(arr));

Output
110
Comment