How to get the largest sum in the 2D array in O (n)?


I need to calculate the biggest sum possible in 2D array, but the code must be in the efficiency of O(n). n is the number of numbers we have in the array.

The array is like stairs, and the user just needs to enter N numbers. We don't need to check if it's a valid number.

The numbers will be shown in array like this:


2 3

4 5 6

7 8 9 10

In every row there is one more number.

You need to get the biggest sum path possible, starting from first or last row. At each iteration you can move only one step down, or one step diagonally down and left / down and right.

That means that if you start from the first row, you can go to 2 or 3. Let's say you go for 2; now you can go only for 4 or 5. If you choose 5, you can go just to 7 or 8 or 9. Or if you want you can go to 1 > 3 > 6 > 8. But you cannot go to 1 > 2 > 6 > 10 because 2 isn't connected with 6.

You also can select only one number in a row. You can't go 1 > 2 > 3 > 6 > 8 > 9 > 10 or something like that.

We can also change the value of a cell, but the path must be the same. That means that I can change, for example, 9 to be 50, but it won't be good because it was not a good path in the original array. (The max sum path in this array 1 > 3 > 6 > 10, so i cant go to different cells)

My problem is that I need this code to run with efficiency of O(n).

I tried to go from the last line and check every valid path that it can go, I tried to go all ways for the biggest number in each possibility. The first one isn't O(n) efficiency and the second one can get the wrong answer.

I also tried to do it from the first row and to scan and compare all the steps, but again it's not O(n) efficiency.

Just to make sure, I'm not requesting anyone to write the code for me, just to help me figure out what is the best way to calculate it.

BTW, saw few comments and wanted to add that at the end, I need to print the maximum path sum, but not the path itself.

You can determine the maximum sum from the bottom up. For example, the two bottom rows are:

  4   5   6
 / \ / \ / \
7   8   9  10

Now accumulate the maximum possible sum to the second but last row:

 12  14  16
 / \ / \ / \
7   8   9  10

Foe example, the maximum you can make from either 7 or 8 at node 4 is 12. Continue this, but with the max-sum values, to the top:

     / \
   16  19
   / \ / \
 12  14  16
 / \ / \ / \
7   8   9  10

The top node now has the maximum possible sum: 1 + 3 + 6 + 10 == 20. This approach will destroy the original data (because it overwrites it with the max-sums) and it will not give you the path, only the value of the maximum sum.

Here, the triangular array looks like a tree, but you don't really build a tree: The links can easily be described by their positions.

Edit: I now realise that this doesn't quite solve your question, because it omits the possible step to the left, but the principle still is good: Accumulate the maximum possible sub-sums from the bottom up, except that you need to consider the three values below, not only two. (I'm a bit loth to redraw the ASCII trees. :-)

Edit II: As @rpattiso points out, you have the optimum path in the accumulated tree by following the maximum sum of the three possible child nodes from the top.

Edit III: When you treat the matrix as stairs and consider three children of each node, the graph becomes:

   | \
  16  19
   | X | \
  12  14  16
   | X | X | \
   7   8   9  10

Here, the X mean two crossing paths. Note that the first column is a special case, because nodes in this column have only two children.

If m is the number of rows and n = m*(m + 1)/2 is the number of cells and if your array is represented by a two-dimensional C-style array a[row][col], then your max-sum algorithm is:

int row = m - 1;

while (row--) {
    a[row][0] += max(a[row + 1][0], a[row + 1][1]);

    for (int col = 1; col < row + 1; col++) {
        int a1 = a[row + 1][col - 1];
        int a2 = a[row + 1][col];
        int a3 = a[row + 1][col + 1];

        a[row][col] += max(a1, a2, a3);

You maximum sum is the value of a[0][0].