304. Range Sum Query 2D - Immutable 等题

303. Range Sum Query

原题:
Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.

Example:

Given nums = [-2, 0, 3, -5, 2, -1]

sumRange(0, 2) -> 1
sumRange(2, 5) -> -1
sumRange(0, 5) -> -3

Note:
You may assume that the array does not change.
There are many calls to sumRange function.

题解:
简单的动态规划题,要求一个范围内的数字和,如果知道从第一个数字到每个数字的和,那么可以通过一次减法得到一个范围的和。因此用一维数组f[x]储存[0,x]范围内的数字和,sumRange则返回一个差。

代码:

class NumArray {
public:
    NumArray(vector<int> &nums) {
        if(nums.empty()) {
            return;
        }
        this->f.resize(nums.size());
        f[0] = nums[0];
        for(int i=1; i<nums.size(); ++i) {
            f[i] = f[i-1] + nums[i];
        }
    }

    int sumRange(int i, int j) {
        return (i? this->f[j] - this->f[i-1]: this->f[j]);
    }
private:
    vector<int> f;
};

304. 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).

Range Sum Query 2D

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

Example:

Given matrix = [
  [3, 0, 1, 4, 2],
  [5, 6, 3, 2, 1],
  [1, 2, 0, 1, 5],
  [4, 1, 0, 1, 7],
  [1, 0, 3, 0, 5]
]

sumRegion(2, 1, 4, 3) -> 8
sumRegion(1, 1, 2, 2) -> 11
sumRegion(1, 2, 2, 4) -> 12

Note:
You may assume that the matrix does not change.
There are many calls to sumRegion function.
You may assume that row1 ≤ row2 and col1 ≤ col2.

题解:
思想和上一题差不多,如果要求一个处于中间的矩阵的和,例如(1,1)到(3,3)之间,那么就可以分解为:

sum(1,1,3,3) = sum(0,0,3,3) - sum(0,0,1,3) - sum(0,0,3,1) + sum(0,0,0,0);

把它想象成取一个二维的面积就容易理解多了。

这里写图片描述

要求淡蓝色范围内的和,则等价于

= 红框和 - 上方淡橙色范围和 - 左边淡橙色范围和 + 深橙色范围和

因此问题变为:如何得到(0,0)到各个顶点的范围元素和。我使用这样的方法:

这里写图片描述

建立一个二维数组f,大小为matrix的宽高各加一。f[x][y] 表示从 (x, y) 到原点 (0, 0) 的范围内的所有元素和,例如:

sumRange(0,0,2,2) = f[3][3]

通过动态规划的思想来生成这个f数组:

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

如果不能理解,可以画一个图来推导。

获得这个数组之后,sumRange函数表达式为:

sumRange(row1, col1, row2, col2) = f[row2+1][col2+1] - f[row1][col2+1] - f[row2+1][col1] + f[row1][col1];

代码:

class NumMatrix {
public:
    vector<vector<int>> f;
    NumMatrix(vector<vector<int>> &matrix) {
        if(matrix.empty() || matrix[0].empty()) {
            return;
        }
        f.push_back(vector<int>(matrix[0].size() + 1));
        for(int i=1; i<=matrix.size(); ++i) {
            f.push_back(vector<int>(matrix[0].size() + 1));
            for(int j=1; j<=matrix[0].size(); ++j) {
                f[i][j] = f[i-1][j] + f[i][j-1] + matrix[i-1][j-1] - f[i-1][j-1];
            }
        }
    }

    int sumRegion(int row1, int col1, int row2, int col2) {
        return f[row2+1][col2+1] - f[row1][col2+1] - f[row2+1][col1] + f[row1][col1];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值