一维数组前缀和与差分
前缀和
核心概念:
前缀和数组 prefix 中,prefix[i] 表示原数组 arr 前 i 个元素的和(arr[0] + arr[1] + ... + arr[i-1])。通过前缀和可快速计算原数组任意区间 [l, r] 的和:sum(l, r) = prefix[r+1] - prefix[l]。跟我们高中学的数列,前n项和类似。
import java.util.Scanner;
public class PrefixSumWithInput{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int[]arr=new int[n];
for(int i=0;i<n;i++){
arr[i]=sc.nextInt();
}
// 3. 构建前缀和数组
int[]prefix=new int[n + 1]; // 前缀和数组长度为 n+1,prefix[0] = 0
for(int i=0;i<n;i++){
prefix[i+1]=prefix[i]+arr[i]; // 核心公式:累加前 i 个元素
}
int l=sc.nextInt();
int r=sc.nextInt();
if(l<0||r>=n||l>r){
return;
}else{
int sum=prefix[r+1]-prefix[l];
System.out.println(sum);
}
}
}
差分
核心概念:
差分是一种前缀和的逆运算,用于高效处理数组的**「区间增减」** 操作。通过构建一个「差分数组」,可以将原本 O (n) 时间复杂度的区间更新,优化到 O (1);最终通过差分数组的前缀和,还原出更新后的原数组(时间复杂度 O (n))原数组:nums0...n-1,差分数组:diff0...n(通常比原数组多一位,避免边界判断)差分数组的前缀和 = 原数组,即 numsi = diff0 + diff1 + ... + diffi。
import java.util.Arrays;
public class Difference{
public static void main(String[]args){
// 1. 原数组(直接替换为目标数组)
int[]nums={}; // 此处替换为你的原数组
int n = nums.length;
// 2. 构建差分数组(核心公式)
int[]diff=new int[n+1];
if(n>0){
diff[0]=nums[0];
for(int i=1;i<n;i++){
diff[i]=nums[i]-nums[i-1];
}
}
// 3. 区间更新(按需添加,格式:[l, r] 加 val,可多个)
diff[l] += val;
diff[r + 1] -= val;
// 4. 还原更新后的数组(前缀和)
int[] res=new int[n];
if(n>0){
res[0]=diff[0];
for(int i=1;i<n;i++){
res[i]=res[i-1]+diff[i];
}
}
// 输出结果
System.out.println(Arrays.toString(res));
}
}
二维数组的前缀和与差分
前缀和
左+上-左上+自己

public class NumMatrix {
public int[][] sum;
public NumMatrix(int[][] matrix) {
int n = matrix.length;
int m = matrix[0].length;
sum = new int[n + 1][m + 1];
for (int a = 1, c = 0; c < n; a++, c++) {
for (int b = 1, d = 0; d < m; b++, d++) {
sum[a][b] = matrix[c][d];
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
sum[i][j] += sum[i][j - 1] + sum[i - 1][j] - sum[i - 1][j - 1];
}
}
}
public int sumRegion(int a, int b, int c, int d) {
c++;
d++;
return sum[c][d] - sum[c][b] - sum[a][d] + sum[a][b];
}
}
二维差分

import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int k = sc.nextInt();
// 差分数组开大一点,防止越界
int[][] diff = new int[n + 2][m + 2];
for (int i = 0; i < k; i++) {
int x1 = sc.nextInt();
int y1 = sc.nextInt();
int x2 = sc.nextInt();
int y2 = sc.nextInt();
int c = sc.nextInt();
// 二维差分核心操作
diff[x1][y1] += c;
diff[x1][y2 + 1] -= c;
diff[x2 + 1][y1] -= c;
diff[x2 + 1][y2 + 1] += c;
}
// 求二维前缀和,得到最终矩阵
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
diff[i][j] += diff[i - 1][j] + diff[i][j - 1] - diff[i - 1][j - 1];
System.out.print(diff[i][j] + " ");
}
System.out.println();
}
}
}