前缀和【超详细整理】

前缀和

1.1 定义

  • 前缀和就是从位置1到位置i这个区间内的所有的数字之和。不明白请看下面的例子。
  • 前缀和分为一维前缀和二维前缀和

1.2 一维前缀和

  • 我们先给出一个数组src[6]={1,2,3,4,5,6}
  • 这个数列的前缀和prefixSum[6]
    prefixSum[0]=src[0]=1
    prefixSum[1]=src[0]+src[1]=3
    prefixSum[2]=src[0]+src[1]+src[2]=6
    prefixSum[3]=src[0]+src[1]+src[2]+src[3]=10
    prefixSum[4]=src[0]+src[1]+src[2]+src[3]+src[4]=15
    prefixSum[5]=src[0]+src[1]+src[2]+src[3]+src[4]+src[5]=21
    由此得出结论:prefixSum[i]=prefixSum[i-1]+src[i]

代码理解

for (int i = 0; i < n; i ++ ){
	cin >> src[i];
	if(i == 0) prefixSum[i] = src[0];
	prefixSum[i] = prefixSum[i - 1] + src[i];
}

1.3 二维前缀和

分为四种情况:

  • i==0 ,只有一个直接赋值即可:prefixSum[0, 0] = src[0, 0]。
  • i==0,最左边的一排,图中黄色部分,prefixSum[0, j] = prefixSum[0, j-1] + src[0, j];
  • j==0,最上面一排,途中红色部分,prefixSum[i, o] = prefixSum[i-1, 0] + src[i, 0];
  • i!=0 || j!=0,图中绿色部分,prefixSum[i][j] = prefixSum[i - 1][j] + prefixSum[i][j - 1] + src[i][j] - prefixSum[i - 1][j - 1];

我们具体讲第四步:如图所示。54=33+21+12-1在这里插入图片描述

#include <iostream>
#include <vector>

using namespace std;

vector<vector<int>> twoDimen(vector<vector<int>> src) {
    vector<vector<int>> prefixSum(src.size(),vector<int>(src[0].size()));
    for (int i = 0; i < src.size(); i++) {
        for (int j = 0; j < src[0].size(); j++) {
            if (i == 0 && j == 0) {//第0个,最左上角
                prefixSum[i][j] = src[i][j];
            } else if (i == 0) {//第一行,最顶部一行
                prefixSum[i][j] = prefixSum[i][j - 1] + src[i][j];
            } else if (j == 0) {//第一列,最左边一列
                prefixSum[i][j] = prefixSum[i - 1][j] + src[i][j];
            } else {//其他
                prefixSum[i][j] = prefixSum[i - 1][j] + prefixSum[i][j - 1] + src[i][j] - prefixSum[i - 1][j - 1];
            }
        }
    }
    return prefixSum;
}
int main() {
    vector<vector<int>> src={{0,1,2},{5,6,7},{10,11,12}};//定义一个3*3的矩阵
    vector<vector<int>> prefixSum;//二维前缀和矩阵
    for (auto iter: twoDimen(src)){
        for (auto it:iter)
            cout << it << " ";
        cout << endl;
    }
    return 0;
}

1.4 前缀和的应用

  • 优势:可以快速得到某一个区间的区间总和。

例题

输入n个数的数列,所有相邻m数的和有n-m+1个,求其中的最小值。
比如:数组为:[10, 4, 1, 5, 5, 2]
m为:3
结果为:10

#include <iostream>
#include <vector>

using namespace std;

int minSum(vector<int> src , int m) {
    if (m <= 0) {
        return 0;
    }
    vector<int> prefixSum(src.size());
    for (int i = 0; i < prefixSum.size(); ++i) {
        if (i == 0) {
            prefixSum[i] = src[i];
        } else {
            prefixSum[i] = prefixSum[i - 1] + src[i];
        }
    }
    //first是第一个三个数之和 prefixSum数组中的第一个值
    //second=prefixSum[3]-prefixSum[0]
    int first = prefixSum[m - 1], result = first;
    for (int i = m; i < prefixSum.size(); ++i) {
    	//第(i+1)位置的前缀和-(i-m+1)的前缀和 后续三个数的和
        int current = prefixSum[i] - prefixSum[i - m]; 
        result = current > result ? result : current;
    }

    return result;
}
int main() {
    vector<int> src={10,4,1,5,5,2};
    int m;
    cin >> m;
    cout << minSum(src,m) << endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值