什么是前缀和?前缀和就是一个数组的某项下标之前(包括此项元素)的所有数组中的元素的和。
一维前缀和与差分
设
s
u
m
sum
sum为前缀和数组,
a
r
r
arr
arr为原数组,那么就存在:
s
u
m
[
i
]
=
a
r
r
[
0
]
+
a
r
r
[
1
]
+
.
.
.
+
a
r
r
[
i
]
sum[i]=arr[0]+arr[1]+...+arr[i]
sum[i]=arr[0]+arr[1]+...+arr[i]
可以得到如下递推式:
s
u
m
[
i
]
=
s
u
m
[
i
−
1
]
+
a
r
r
[
i
]
sum[i]=sum[i-1]+arr[i]
sum[i]=sum[i−1]+arr[i]
可以得到:
a
r
r
[
j
]
+
a
r
r
[
j
+
1
]
+
.
.
.
+
a
r
r
[
i
]
=
s
u
m
[
i
]
−
s
u
m
[
j
−
1
]
arr[j]+arr[j+1]+...+arr[i]=sum[i]-sum[j-1]
arr[j]+arr[j+1]+...+arr[i]=sum[i]−sum[j−1]
题目一:leetcode 560. 和为 K 的子数组
给你一个整数数组 n u m s nums nums 和一个整数 k k k ,请你统计并返回该数组中和为 k k k 的连续子数组的个数。
示例 1:
输入:nums = [1,1,1], k = 2
输出:2
示例 2:
输入:nums = [1,2,3], k = 3
输出:2
提示:
1 <=
n
u
m
s
.
l
e
n
g
t
h
nums.length
nums.length <=
2
∗
1
0
4
2 * 10^4
2∗104
-1000 <=
n
u
m
s
[
i
]
nums[i]
nums[i] <= 1000
−
1
0
7
-10^7
−107 <=
k
k
k<=
1
0
7
10^7
107
代码
import java.util.HashMap;
class Solution {
public int subarraySum(int[] nums, int k) {
//return method1(nums,k); //0(n^2)
return method2(nums,k);//0(n)
}
/*
利用前缀和,时间复杂度0(n^2)
*/
public int method1(int[] nums,int k){
int res=0;
for(int i=0;i<nums.length;i++){
int cur=0;
for(int j=i;j<nums.length;j++){
cur+=nums[j];
if(cur==k) res++;
}
}
return res;
}
/*
利用前缀和 + Map优化 时间复杂度0(n)
前缀和数组sum[i]=arr[0]+arr[1]+...+arr[i]
若arr[j]+arr[j+1]+...+arr[i]=k,则有sum[i]-sum[j-1]=k
也就是说,对于sum[i],如果存在sum[j-1]=sum[i]-k,那么就可以求出j,
从而可以得到该子数组
设置map<sum,number>,sum:前缀和,number:前缀和为sum的前缀和数组个数
*/
public int method2(int[] nums,int k){
HashMap<Integer,Integer> map=new HashMap<>();
map.put(0,1);
int n=nums.length;
int[] sum=new int[n];
sum[0]=nums[0];
for(int i=1;i<n;i++){
sum[i]=sum[i-1]+nums[i];
}
int res=0;
for(int i=0;i<n;i++){
if(map.containsKey(sum[i]-k)){
res+=map.get(sum[i]-k);
}
if(map.containsKey(sum[i])){
map.put(sum[i],map.get(sum[i])+1);
}else{
map.put(sum[i],1);
}
}
return res;
}
}
二维前缀和与差分
设 s u m sum sum为前缀和数组, a r r arr arr为原数组,那么就存在:
s u m [ x ] [ y ] sum[x][y] sum[x][y]= ∑ i = 0 x \displaystyle\sum_{i=0}^{x} i=0∑x ∑ j = 0 y a r r [ i ] [ j ] \displaystyle\sum_{j=0}^{y} arr[i][j] j=0∑yarr[i][j]
根据下面的图片,可以得到如下递推式:
s u m [ x ] [ y ] = s u m [ x − 1 ] [ y ] + s u m [ x ] [ y − 1 ] − s u m [ x − 1 ] [ y − 1 ] + a r r [ x ] [ y ] sum[x][y]=sum[x-1][y]+sum[x][y-1]-sum[x-1][y-1]+arr[x][y] sum[x][y]=sum[x−1][y]+sum[x][y−1]−sum[x−1][y−1]+arr[x][y]
可以得到
∑
i
=
x
1
x
2
\displaystyle\sum_{i=x1}^{x2}
i=x1∑x2
∑
j
=
y
1
y
2
a
r
r
[
i
]
[
j
]
\displaystyle\sum_{j=y1}^{y2} arr[i][j]
j=y1∑y2arr[i][j] =
s
u
m
[
x
2
]
[
y
2
]
−
s
u
m
[
x
1
−
1
]
[
y
2
]
−
s
u
m
[
x
2
]
[
y
1
−
1
]
+
s
u
m
[
x
1
−
1
]
[
y
1
−
1
]
sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1]
sum[x2][y2]−sum[x1−1][y2]−sum[x2][y1−1]+sum[x1−1][y1−1]
如上图所示,
s
u
m
[
x
]
[
y
]
=
红
色
区
域
的
值
+
黄
色
区
域
的
值
+
蓝
色
区
域
的
值
+
绿
色
区
域
的
值
sum[x][y]=红色区域的值+黄色区域的值+蓝色区域的值+绿色区域的值
sum[x][y]=红色区域的值+黄色区域的值+蓝色区域的值+绿色区域的值
各区域的值分别如下:
蓝
色
区
域
的
值
=
s
u
m
[
x
−
1
]
[
y
]
−
s
u
m
[
x
−
1
]
[
y
−
1
]
蓝色区域的值=sum[x-1][y]-sum[x-1][y-1]
蓝色区域的值=sum[x−1][y]−sum[x−1][y−1]
黄
色
区
域
的
值
=
s
u
m
[
x
]
[
y
−
1
]
−
s
u
m
[
x
−
1
]
[
y
−
1
]
黄色区域的值=sum[x][y-1]-sum[x-1][y-1]
黄色区域的值=sum[x][y−1]−sum[x−1][y−1]
红
色
区
域
的
值
=
s
u
m
[
x
−
1
]
[
y
−
1
]
红色区域的值=sum[x-1][y-1]
红色区域的值=sum[x−1][y−1]
绿
色
区
域
的
值
=
a
r
r
[
x
]
[
y
]
绿色区域的值=arr[x][y]
绿色区域的值=arr[x][y]
综上所述,可以得到:
s
u
m
[
x
]
[
y
]
=
s
u
m
[
x
−
1
]
[
y
]
+
s
u
m
[
x
]
[
y
−
1
]
−
s
u
m
[
x
−
1
]
[
y
−
1
]
+
a
r
r
[
x
]
[
y
]
sum[x][y]=sum[x-1][y]+sum[x][y-1]-sum[x-1][y-1]+arr[x][y]
sum[x][y]=sum[x−1][y]+sum[x][y−1]−sum[x−1][y−1]+arr[x][y]
如上图所示
∑
i
=
x
1
x
2
\displaystyle\sum_{i=x1}^{x2}
i=x1∑x2
∑
j
=
y
1
y
2
a
r
r
[
i
]
[
j
]
\displaystyle\sum_{j=y1}^{y2} arr[i][j]
j=y1∑y2arr[i][j] =
绿
色
区
域
的
值
绿色区域的值
绿色区域的值
s
u
m
[
x
2
]
[
y
2
]
=
绿
色
+
黄
色
+
红
色
+
蓝
色
区
域
的
值
sum[x2][y2]=绿色+黄色+红色+蓝色区域的值
sum[x2][y2]=绿色+黄色+红色+蓝色区域的值
s
u
m
[
x
1
−
1
]
[
y
2
]
=
红
色
+
蓝
色
区
域
的
值
sum[x1-1][y2]=红色+蓝色区域的值
sum[x1−1][y2]=红色+蓝色区域的值
s
u
m
[
x
2
]
[
y
1
−
1
]
=
红
色
+
黄
色
区
域
的
值
sum[x2][y1-1]=红色+黄色区域的值
sum[x2][y1−1]=红色+黄色区域的值
s
u
m
[
x
1
−
1
]
[
y
1
−
1
]
=
红
色
区
域
的
值
sum[x1-1][y1-1]=红色区域的值
sum[x1−1][y1−1]=红色区域的值
绿
色
区
域
的
值
=
s
u
m
[
x
2
]
[
y
2
]
−
s
u
m
[
x
1
−
1
]
[
y
2
]
−
s
u
m
[
x
2
]
[
y
1
−
1
]
+
s
u
m
[
x
1
−
1
]
[
y
1
−
1
]
绿色区域的值=sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1]
绿色区域的值=sum[x2][y2]−sum[x1−1][y2]−sum[x2][y1−1]+sum[x1−1][y1−1]
那么就可以得到:
∑ i = x 1 x 2 \displaystyle\sum_{i=x1}^{x2} i=x1∑x2 ∑ j = y 1 y 2 a r r [ i ] [ j ] \displaystyle\sum_{j=y1}^{y2} arr[i][j] j=y1∑y2arr[i][j] = s u m [ x 2 ] [ y 2 ] − s u m [ x 1 − 1 ] [ y 2 ] − s u m [ x 2 ] [ y 1 − 1 ] + s u m [ x 1 − 1 ] [ y 1 − 1 ] sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1] sum[x2][y2]−sum[x1−1][y2]−sum[x2][y1−1]+sum[x1−1][y1−1]
相关习题