Skip to content
dsa450for five year olds

Greedy · 17 of 35

Maximize the sum of arr[i] times i

Put number cards into numbered boxes that multiply them, and win the most points by giving the biggest card the biggest box.

Simple way
time O(n! * n)
room O(n)
Clever way
time O(n log n)
room O(1)

The problem, simply

You get a row of numbers. You may put them in any order. Then each number is multiplied by its position, counting from 0: the first number by 0, the second by 1, and so on. Add up all the products.

Give back the biggest total you can make. In code it is the biggest value of arr[0] * 0 + arr[1] * 1 + ... + arr[n - 1] * (n - 1).

A story to remember it

Picture it

array
01231356

Cards [3, 5, 6, 1] sorted into boxes 0 to 3. The small numbers under the boxes are the box numbers, which are also the multipliers.

total
1x0 + 3x1 + 5x2 + 6x3 = 31
  • answer

Examples

A normal case

In
arr = [3, 5, 6, 1]
Out
31

Sorted it is 1, 3, 5, 6, and 1 x 0 + 3 x 1 + 5 x 2 + 6 x 3 = 0 + 3 + 10 + 18 = 31.

Five cards

In
arr = [2, 3, 1, 5, 4]
Out
40

Sorted it is 1, 2, 3, 4, 5, and 0 + 2 + 6 + 12 + 20 = 40.

Negative numbers

In
arr = [-1, 3, -2]
Out
5

Sorted it is -2, -1, 3. The most negative card goes in box 0 where it is multiplied by 0: 0 - 1 + 6 = 5.

One card

In
arr = [7]
Out
0

The only box is box 0, and anything times 0 is 0.

Way 1: the simple way

Try every order of the cards, work out the total for each, and keep the best.

  1. Build every order with swaps, one position at a time.
  2. For a full order, add a[i] * i for every i.
  3. Keep the biggest total.
java
class Solution {
    private long best;

    public long maxIndexSum(int[] a) {
        best = Long.MIN_VALUE;
        tryOrders(a, 0);
        return best;
    }

    private void tryOrders(int[] a, int start) {
        if (start == a.length) {
            long total = 0;
            for (int i = 0; i < a.length; i++) total += (long) a[i] * i;
            best = Math.max(best, total);
            return;
        }
        for (int i = start; i < a.length; i++) {
            swap(a, start, i);
            tryOrders(a, start + 1);
            swap(a, start, i);
        }
    }

    private void swap(int[] a, int i, int j) { int t = a[i]; a[i] = a[j]; a[j] = t; }
}

How long it takes: n! orders, each added up in n steps, so O(n! * n). Extra room: the recursion is n deep, O(n).

Way 2: the clever way

Think about two cards, a small one s and a big one b, in two boxes i < j. If the big card is in the big box, they give s * i + b * j. If you swap them, they give b * i + s * j. The difference is (b - s) * (j - i), which is never negative. So a big card in a small box is always a mistake you can fix by swapping. Keep fixing and you end with the cards sorted.

  1. Sort the cards from small to big.
  2. Add a[i] * i for every box i.

Sort, then fill the boxes from 0 up

01 / 08

arraycards
01233561

Four cards to put in boxes 0, 1, 2 and 3. Each box multiplies its card by the box number.

  • looking now
  • done
  • answer
  • rejected
  • just added
java
import java.util.Arrays;

class Solution {
    public long maxIndexSum(int[] a) {
        Arrays.sort(a);                       // small cards in small boxes
        long total = 0;
        for (int i = 0; i < a.length; i++) {
            total += (long) a[i] * i;         // card times box number
        }
        return total;
    }
}

How long it takes: the sort is O(n log n) and the adding is O(n). Extra room: O(1) beyond the sort.

Watch out for

  • Boxes start at 0, not 1. If the problem counts from 1, the order is the same but the total is bigger by the sum of all cards.
  • Negative cards need no special care. Sorting puts the most negative one in box 0, where it costs nothing.
  • Do not sort from big to small. That gives the smallest total, not the biggest.

What interviewers ask next

  • Minimise the total instead? Sort from big to small, so the biggest card sits in box 0.
  • You may only rotate the row, not reorder it. Find the best rotation in O(n): each rotation by one place changes the total by sum - n * x, where x is the card that moves from the last box to box 0.
  • Pair two rows to make the biggest sum of products. Sort both the same way. This is the rearrangement inequality, the same exchange idea.
  • Why is the swap argument enough? Any order that is not sorted has a neighbouring pair in the wrong order, and swapping it never lowers the total, so you can walk to the sorted order without ever losing.

Remember this

Grown-up words: the boxes are array indices, the steps game is a weighted sum, the swap trick is an exchange argument, and sorting both rows the same way is the rearrangement inequality.