和为零的子矩阵

给定一个整数矩阵,请找出一个子矩阵,使得其数字之和等于0.输出答案时,请返回左上数字和右下数字的坐标。

样例

给定矩阵

[
  [1 ,5 ,7],
  [3 ,7 ,-8],
  [4 ,-8 ,9],
]

返回 [(1,1), (2,2)]

挑战

O(n3) 时间复杂度。

class Solution {
public:
    /**
     * @param matrix an integer matrix
     * @return the coordinate of the left-up and right-down number
     */
    vector<vector<int>> submatrixSum(vector<vector<int>>& matrix) {
        // Write your code here
        int h = matrix.size();
        if (!h) 
        {
            return {};
        }
        int w = matrix[0].size();
        if (!w) 
        {
            return {};
        }

        // Get accumulate sum by columns
        vector<vector<int>> cols(h, vector<int>(w, 0));        
        for (int i = 0; i < w; i ++)
        {
            unordered_map<int, int> rec; // sum-inx
            for (int j = 0; j < h; j ++)
            {
                if (matrix[j][i] == 0)
                {
                    return {{i, j},{i, j}};
                }

                cols[j][i] = (j ? cols[j - 1][i] : 0) + matrix[j][i];
                if (!cols[j][i])
                {
                    return {{0, i}, {j, i}};
                }
                else if (rec.find(cols[j][i]) != rec.end())
                {
                    return {{rec[cols[j][i]] + 1, i}, {j, i}};
                }
                rec[cols[j][i]] = j;
            }
        }

        //  horizontal case
        for (int i = 0; i < h; i++)
        {
            for (int j = i; j < h; j++)
            {
                vector<int> hsum(w, 0);
                for (int x = 0; x < w; x ++)
                {
                    int prev = ((i == 0) ? 0 : cols[i - 1][x]);
                    hsum[x] = cols[j][x] - prev;
                }
                // 
                vector<int> asum(w, 0);
                unordered_map<int, int> rec; // sum-inx
                for (int x = 0; x < w; x ++)
                {
                    int nsum = (x ? asum[x - 1] : 0) + hsum[x];
                    if (!nsum)
                    {
                        return {{i + 1, 0}, {j, x}};
                    }
                    else if (rec.find(nsum) != rec.end())
                    {
                        return {{i, rec[nsum] + 1}, {j, x}};
                    }
                    rec[nsum] = x;
                    asum[x] = nsum;
                }
            }
        }

        return {};
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值