views:

814

answers:

3

With the help of the Algorithmist and Larry and a modification of Kadane's Algorithm, here is my solution:

int dim = matrix.length;
    //computing the vertical prefix sum for columns
    int[][] ps = new int[dim][dim];
    for (int i = 0; i < dim; i++) {
        for (int j = 0; j < dim; j++) {
            if (j == 0) {
                ps[j][i] = matrix[j][i];
            } else {
                ps[j][i] = matrix[j][i] + ps[j - 1][i];
            }
        }
    }
    int maxSoFar = 0;
    int min , subMatrix;
    //iterate over the possible combinations applying Kadane's Alg.
    //int toplefti =0, topleftj=0, bottomrighti=0, bottomrightj=0;
    for (int i = 0; i < dim; i++) {
        for (int j = i; j < dim; j++) {
            min = 0;
            subMatrix = 0;
            for (int k = 0; k < dim; k++) {
                if (i == 0) {
                    subMatrix += ps[j][k];
                } else {
                    subMatrix += ps[j][k] - ps[i-1][k];
                }
                if(subMatrix < min){                        
                    min = subMatrix;
                }
                if((subMatrix - min) > maxSoFar){
                    maxSoFar = subMatrix - min;
                }                    
            }
        }
    }

The only problem left is to determine the submatrix elements, i mean the top left and the bottom right corners. I managed to do this in one dimensional case. Any suggestions?

A: 

Have a look at JAMA package; I believe it will make your life easier.

Anax
Thanks Anax. It is a useful package and i've never heard about it, but i think i need to use standard API, it is kinda algorithm problem.
guirgis
+3  A: 

This is a Dynamic Programming problem, and you can read about the O(N^3) solution at Algorithmist.

Larry
Thanks Larry. According to that algorithm, this should be the 1st step:int dim = matrix.length; int[][] ps = new int[dim][dim]; for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { if (j == 0) { ps[i][j] = matrix[i][j]; } else { ps[i][j] = matrix[i][j] + ps[i][j - 1]; } } }The second step is to get the n^2 combinations and apply the alg. i posted earlier on them to find the maximum. so my problem now is to find these combinations.Anyone help?
guirgis
I mean each combination should be 1-dimensional array that is passed to function that compute the maximum subarray, how do i get these arrays from the matrix of partial sums?
guirgis
Well, there are `n^2` rows, so that's your combination. If you already have the partial sums, you can query the sum of the next column (within these rows) in `O(1)` time, which would be analogous to processing a single element in the traditional 1D Kadane's algorithm.
Larry
+1  A: 

With the help of the Algorithmist and Larry and a modification of Kadane's Algorithm, here is my solution:

int dim = matrix.length;
    //computing the vertical prefix sum for columns
    int[][] ps = new int[dim][dim];
    for (int i = 0; i < dim; i++) {
        for (int j = 0; j < dim; j++) {
            if (j == 0) {
                ps[j][i] = matrix[j][i];
            } else {
                ps[j][i] = matrix[j][i] + ps[j - 1][i];
            }
        }
    }
    int maxSoFar = 0;
    int min , subMatrix;
    //iterate over the possible combinations applying Kadane's Alg.
    for (int i = 0; i < dim; i++) {
        for (int j = i; j < dim; j++) {
            min = 0;
            subMatrix = 0;
            for (int k = 0; k < dim; k++) {
                if (i == 0) {
                    subMatrix += ps[j][k];
                } else {
                    subMatrix += ps[j][k] - ps[i - 1 ][k];
                }
                if(subMatrix < min){
                    min = subMatrix;
                }
                if((subMatrix - min) > maxSoFar){
                    maxSoFar = subMatrix - min;
                }                    
            }
        }
    }

The only thing left is to determine the submatrix elements, i.e: the top left and the bottom right corner of the submatrix. Anyone suggestion?

guirgis
Just keep track of it in your if statements. By the way, it's probably better to edit your original question as opposed to submitting an answer.
Larry
I managed to do this in the 1-dimensional problem:for (int i = 0; i < a.length; i++) { subArray += a[i]; if(subArray < min){ offset = i+1; min = subArray; } if((subArray - min) > best){ length ++; best = subArray - min; } }But i had some problems in the matrix case.Excuse me being newbie here, i don't know what is best.
guirgis
Well, if you store an offset variable, you would already know i, j, and k, so you can figure out the corners of the submatrix from that.
Larry
Thanks Larry for your help. I know that this is what i should do but the problem is i can't determine where the offset will be knowing the "min" element coordinates, also how to apply the length value to find the right corner.
guirgis
Any help fellows?
guirgis