leetcode笔记:Range Sum Query 2D - Immutable

一. 题目描述

Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2).

leetcode笔记:Range Sum Query 2D - Immutable_第1张图片

The above rectangle (with the red border) is defined by (row1, col1) = (2, 1) and (row2, col2) = (4, 3), which contains sum = 8.

二. 题目分析

题目大意是,给定一个二维矩阵,计算从下标(row1, col1) 到下标: (row2, col2)的子矩阵的和。题目给出了几个测试用例。

注意事项中提到:

  • 假设矩阵不会改变;
  • sumRegion(查询)函数会调用很多次;
  • 假设row1 ≤ row2, 并且 col1 ≤ col2

该题的重点是使当多次调用sumRegion函数时,算法能保持高效,因此最直观的方法是使用空间换取时间,通过构造辅助数组sumRecordsumRecord[i][j]表示从下标(0, 0)(x, y)的子矩阵的和(考虑到边界问题,辅助数组sumRecord大小设为(m + 1) * (n + 1),其中mn分别为数组matrix的行数和列数),使得题目转化为求取矩形边界的问题,如下面所示。

没有手动画图,引用网上的系列图片进行解释:

+-----+-+-------+     +--------+-----+     +-----+---------+     +-----+--------+
|     | |       |     |        |     |     |     |         |     |     |        |
|     | |       |     |        |     |     |     |         |     |     |        |
+-----+-+       |     +--------+     |     |     |         |     +-----+        |
|     | |       |  =  |              |  +  |     |         |  -  |              |
+-----+-+       |     |              |     +-----+         |     |              |
|               |     |              |     |               |     |              |
|               |     |              |     |               |     |              |
+---------------+     +--------------+     +---------------+     +--------------+

 sumRecord[i][j]   =  sumRecord[i-1][j]  + sumRecord[i][j-1]  - sumRecord[i-1][j-1] +  
 matrix[i-1][j-1]

这是小学学过的简单的矩形求面积方法,对于本题正好适用。

三. 示例代码

class NumMatrix {
public:
    NumMatrix(vector<vector<int>> &matrix) {
        int m = matrix.size();
        int n = m > 0 ? matrix[0].size() : 0;
        sumRecord = vector<vector<int>>(m + 1, vector<int>(n + 1, 0));
        // 由于sumRegion函数可能被调用多次,因此使用辅助数组sumRecord用于
        // 记录matrix中坐标(0,0)到任一下标(i,j)之间矩形框内元素的值,这样
        // 每次调用sumRegion函数时只需查询sumRecord里的值并进行简单运算即可
        for (int i = 1; i <= m; ++i)
            for (int j = 1; j <= n; ++j)
                sumRecord[i][j] = matrix[i - 1][j - 1] + sumRecord[i - 1][j] + sumRecord[i][j - 1] - sumRecord[i - 1][j - 1];
    }

    int sumRegion(int row1, int col1, int row2, int col2) {
        return sumRecord[row2 + 1][col2 + 1] - sumRecord[row1][col2 + 1] - sumRecord[row2 + 1][col1] + sumRecord[row1][col1];
    }

private:
    vector<vector<int>> sumRecord;
};


// Your NumMatrix object will be instantiated and called as such:
// NumMatrix numMatrix(matrix);
// numMatrix.sumRegion(0, 1, 2, 3);
// numMatrix.sumRegion(1, 2, 3, 4);

四. 小结

在构造辅助数组时,应考虑边界问题和下标的转换,否则容易出现越界等错误。

你可能感兴趣的:(LeetCode,Algorithm,C++,算法,range)