本文讲解一维前缀和和二维前缀和,配套6道前缀和经典力扣题,在讲解题目的同时提供AC代码
目录
一、一维前缀和
解法一、暴力【模拟】
最差的情况是求出整个数组的和,那么q次查询,即时间复杂度q*n,那么按照题目给的数据10^5*10^5=10^10>10^9在C++下肯定超时了,其他语言在10^10执行次数的情况下也必定超时
解法二、前缀和
问题:为什么下标要从1开始?
初始化:添加虚拟节点(辅助节点),为了处理边界情况,这跟之前讲的动态规划一样的【可以参考我讲解的动态规划系列】。
#include<iostream>
using namespace std;
const int N = 100010;
long long a[N], dp[N];
int n, q;
int main()
{
//当数据规模>=100w时建议用scanf,因为scanf比cin快一倍
//数据规模较小时可以用cin
scanf("%d %d", &n, &q);
//一般前缀和数组下标是从1开始,下标为0时值为0,是辅助状态,无需特判
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
//处理前缀和数组
for (int i = 1; i <= n; ++i) dp[i] = dp[i - 1] + a[i];
while (q--)
{
int l, r;
scanf("%d %d", &l, &r);
printf("%d\n", dp[r] - dp[l - 1]);//计算区间和
}
return 0;
}
二、二维前缀和
解法一、暴力【模拟】
若q次询问,时间复杂度看最差的情况,即每次询问都求整个二维数组的和,那么就为O (m*n*q)
解法二、前缀和
#include<iostream>
using namespace std;
const int N = 1010;
int a[N][N];
long long dp[N][N];
int n, m, q;
int main()
{
//1、读取数据
scanf("%d %d %d", &n, &m, &q);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%d", &a[i][j]);
//2、构造前缀和矩阵
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j+