[CareerCup] 18.12 Largest Sum Submatrix 和最大的子矩阵

 

18.12 Given an NxN matrix of positive and negative integers, write code to find the submatrix with the largest possible sum.

 

这道求和最大的子矩阵,跟LeetCode上的Maximum Size Subarray Sum Equals kMaximum Subarray很类似。这道题不建议使用brute force的方法,因为实在是不高效,我们需要借鉴上面LeetCode中的建立累计和矩阵的思路,我们先来看这道题的第一种解法,由于建立好累计和矩阵,那么我们通过给定了矩阵的左上和右下两个顶点的坐标可以在O(1)的时间内快速的求出矩阵和,所以我们要做的就是遍历矩阵中所有的子矩阵,然后比较其矩阵和,返回最大的即可,时间复杂度为O(n4)。

 

解法一:

vector<vector<int>> precompute(vector<vector<int>> &matrix) {
    vector<vector<int>> sumMatrix = matrix;
    for (int i = 0; i < matrix.size(); ++i) {
        for (int j = 0; j < matrix[i].size(); ++j) {
            if (i == 0 && j == 0) {
                sumMatrix[i][j] = matrix[i][j];
            } else if (j == 0) {
                sumMatrix[i][j] = sumMatrix[i - 1][j] + matrix[i][j];
            } else if (i == 0) {
                sumMatrix[i][j] = sumMatrix[i][j - 1] + matrix[i][j];
            } else {
                sumMatrix[i][j] = sumMatrix[i - 1][j] + sumMatrix[i][j - 1] - sumMatrix[i - 1][j - 1] + matrix[i][j];
            }
        }
    }
    return sumMatrix;
}

int compute_sum(vector<vector<int>> &sumMatrix, int i1, int i2, int j1, int j2) {
    if (i1 == 0 && j1 == 0) {
        return sumMatrix[i2][j2];
    } else if (i1 == 0) {
        return sumMatrix[i2][j2] - sumMatrix[i2][j1 - 1];
    } else if (j1 == 0) {
        return sumMatrix[i2][j2] - sumMatrix[i1 - 1][j2];
    } else {
        return sumMatrix[i2][j2] - sumMatrix[i2][j1 - 1] - sumMatrix[i1 - 1][j2] + sumMatrix[i1 - 1][j1 - 1];
    }
}

int get_max_matrix(vector<vector<int>> &matrix) {
    int res = INT_MIN;
    vector<vector<int>> sumMatrix = precompute(matrix);
    for (int r1 = 0; r1 < matrix.size(); ++r1) {
        for (int r2 = r1; r2 < matrix.size(); ++r2) {
            for (int c1 = 0; c1 < matrix[0].size(); ++c1) {
                for (int c2 = c1; c2 < matrix[0].size(); ++c2) {
                    int sum = compute_sum(sumMatrix, r1, r2, c1, c2);
                    res = max(res, sum); 
                }
            }
        }
    }
    return res;
}

 

其实这道题的解法还能进一步优化到O(n3),根据LeetCode中的那道Maximum Subarray的解法,我们可以对一维数组求最大子数组的时间复杂度优化到O(n),那么我们可以借鉴其的思路,由于二维数组中遍历所有的列数相等的子矩阵的时间为O(n2),每一行的遍历是O(n),所以整个下来的时间复杂度即为O(n3),参见代码如下:

 

解法二:

int max_subarray(vector<int> &array) {
    int res = 0, sum = 0;
    for (int i = 0; i < array.size(); ++i) {
        sum += array[i];
        res = max(res, sum);
        sum = max(sum, 0);
    }
    return res;
}

int max_submatrix(vector<vector<int>> &matrix) {
    if (matrix.empty() || matrix[0].empty()) return 0;
    int res = 0;
    for (int r1 = 0; r1 < matrix.size(); ++r1) {
        vector<int> sum(matrix[0].size());
        for (int r2 = r1; r2 < matrix.size(); ++r2) {
            for (int c = 0; c < matrix[0].size(); ++c) {
                sum[c] += matrix[r2][c];
            }
            int t = max_subarray(sum);
            res = max(res, t);
        }
    }
    return res;
}

 

CareerCup All in One 题目汇总

 

posted @ 2016-05-12 23:14  Grandyang  阅读(2235)  评论(0编辑  收藏  举报
Fork me on GitHub