设
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]代表
(
r
,
c
)
(r,c)
(r,c)为
(
i
,
j
)
(i,j)
(i,j)的时候我们得到的这个小矩形的和。
d
p
[
i
]
[
j
]
=
d
p
[
i
]
[
j
+
1
]
+
新
增
的
最
左
边
的
那
一
列
的
和
−
失
去
的
最
右
边
那
一
列
的
和
=
d
p
[
i
]
[
j
+
1
]
+
∑
a
=
i
−
k
a
=
i
+
k
m
a
t
[
a
]
[
j
−
k
]
−
∑
a
=
i
−
k
a
=
i
+
k
m
a
t
[
a
]
[
j
+
k
+
1
]
dp[i][j]=dp[i][j+1]+新增的最左边的那一列的和-失去的最右边那一列的和=dp[i][j+1]+\sum_{a=i-k}^{a=i+k}mat[a][j-k]-\sum_{a=i-k}^{a=i+k}mat[a][j+k+1]
dp[i][j]=dp[i][j+1]+新增的最左边的那一列的和−失去的最右边那一列的和=dp[i][j+1]+∑a=i−ka=i+kmat[a][j−k]−∑a=i−ka=i+kmat[a][j+k+1]。
d
p
[
i
]
[
j
]
=
d
p
[
i
+
1
]
[
j
]
+
新
增
的
最
上
边
的
那
一
行
的
和
−
失
去
的
最
下
边
那
一
行
的
和
=
d
p
[
i
+
1
]
[
j
]
+
∑
a
=
j
−
k
a
=
j
+
k
m
a
t
[
i
−
k
]
[
a
]
−
∑
a
=
j
−
k
a
=
j
+
k
m
a
t
[
i
+
k
+
1
]
[
a
]
dp[i][j]=dp[i+1][j]+新增的最上边的那一行的和-失去的最下边那一行的和=dp[i+1][j]+\sum_{a=j-k}^{a=j+k}mat[i-k][a]-\sum_{a=j-k}^{a=j+k}mat[i+k+1][a]
dp[i][j]=dp[i+1][j]+新增的最上边的那一行的和−失去的最下边那一行的和=dp[i+1][j]+∑a=j−ka=j+kmat[i−k][a]−∑a=j−ka=j+kmat[i+k+1][a]。
初始状态
d
p
[
m
−
1
]
[
]
n
−
1
]
dp[m-1][]n-1]
dp[m−1][]n−1]计算出来。
为了优化计算速度,设
s
s
u
m
[
]
[
]
,
s
1
s
u
m
[
]
[
]
ssum[][],s1sum[][]
ssum[][],s1sum[][]分别为一行一行的前缀和、一列一列的前缀和,这样我们就可以简化
∑
a
=
i
−
k
a
=
i
+
k
m
a
t
[
a
]
[
j
−
k
]
\sum_{a=i-k}^{a=i+k}mat[a][j-k]
∑a=i−ka=i+kmat[a][j−k]类似于这种式子的计算。
时间复杂度
O
(
n
2
)
O(n^2)
O(n2),大概是这样吧。
一维前缀和代码
classSolution{public:
vector<vector<int>>ssum, s1sum;
vector<vector<int>>matrixBlockSum(vector<vector<int>>& mat,int K){int k = K;int m = mat.size();int n = mat[0].size();if(m ==0|| n ==0){return vector<vector<int>>();}
ssum.resize(m);
s1sum.resize(m);for(int i =0; i < m; i++){
ssum[i].resize(n);
s1sum[i].resize(n);
ssum[i][0]= mat[i][0];}for(int j =0; j < n; j++){
s1sum[0][j]= mat[0][j];}for(int j =1; j < n; j++){for(int i =0; i < m; i++){
ssum[i][j]= ssum[i][j -1]+ mat[i][j];}}for(int i =1; i < m; i++){for(int j =0; j < n; j++){
s1sum[i][j]= s1sum[i -1][j]+ mat[i][j];}}// 至此,两个前缀和计算完毕
vector<vector<int>>dp(m);for(int i =0; i < m; i++){
dp[i].resize(n);}// 下面进行初始状态dp[m-1][n-1]的计算。
dp[m -1][n -1]=0;for(int i =max(m -1- k,0); i < m; i++){if(n -2- k <0){
dp[m -1][n -1]+= ssum[i][n -1]- ssum[i][0];
dp[m -1][n -1]+= mat[i][0];}else{
dp[m -1][n -1]+= ssum[i][n -1]- ssum[i][n -2- k];}}// 从右下角开始,一行一行的计算dp[i][j]for(int i = m -1; i >=0; i--){for(int j = n -1; j >=0; j--){if(i == m -1&& j == n -1){continue;}// 最右边的if(j == n -1){
dp[i][j]= dp[i +1][j];if(i - k >=0){if(j - k -1<0){
dp[i][j]+= ssum[i - k][min(j + k, n -1)]- ssum[i - k][0];
dp[i][j]+= mat[i - k][0];}else{
dp[i][j]+= ssum[i - k][min(j + k, n -1)]- ssum[i - k][j - k -1];}}if(i + k +1< m){if(j - k -1<0){
dp[i][j]+=-(ssum[i + k +1][min(j + k, n -1)]- ssum[i + k +1][0]);
dp[i][j]+=-(mat[i + k +1][0]);}else{
dp[i][j]+=-(ssum[i + k +1][min(j + k, n -1)]- ssum[i + k +1][j - k -1]);}}}// 非最右边的else{
dp[i][j]= dp[i][j +1];if(j - k >=0){if(i - k -1<0){
dp[i][j]+= s1sum[min(i + k, m -1)][j - k]- s1sum[0][j - k];
dp[i][j]+= mat[0][j - k];}else{
dp[i][j]+= s1sum[min(i + k, m -1)][j - k]- s1sum[i - k -1][j - k];}}if(j + k +1< n){if(i - k -1<0){
dp[i][j]+=-(s1sum[min(i + k, m -1)][j + k +1]- s1sum[0][j + k +1]);
dp[i][j]+=-(mat[0][j + k +1]);}else{
dp[i][j]+=-(s1sum[min(i + k, m -1)][j + k +1]- s1sum[i - k -1][j + k +1]);}}}}}return dp;}};