算法精讲——前缀和:小白也能秒懂的时空魔法

算法精讲------前缀和:小白也能秒懂的时空魔法 ✨

📖 本文配套练习:力扣前缀和专题

🧑💻 建议边看边敲代码体验更佳哦~


🌰 从存钱罐说起------什么是前缀和?

想象你有个存钱罐📦,每天记录存入金额:

天数 1 2 3 4 5
金额 2 5 1 3 4

如果要算第3天到第5天存了多少钱,传统做法是:1+3+4=8元💰 前缀和的做法是:预先计算累计金额,这样就能快速查询任意区间的和!

java 复制代码
// 前缀和数组计算(索引从1开始更直观)
int[] nums = {2,5,1,3,4};
int[] preSum = new int[nums.length+1];

for(int i=1; i<=nums.length; i++){
    preSum[i] = preSum[i-1] + nums[i-1]; 
}
// 得到 [0,2,7,8,11,15]

🧩 一维前缀和实战教学

例题1:基础查询(力扣303)

区域和检索 - 数组不可变

graph LR A[原始数组] --> B[构造前缀数组] B --> C{查询请求} C --> D[计算差值]

Java实现细节

java 复制代码
class NumArray {
    private int[] preSum;
  
    // 初始化:O(n)时间
    public NumArray(int[] nums) {
        preSum = new int[nums.length + 1];
        for (int i = 1; i <= nums.length; i++) {
            preSum[i] = preSum[i-1] + nums[i-1];
        }
    }
  
    // 查询:O(1)时间
    public int sumRange(int left, int right) {
        return preSum[right+1] - preSum[left];
    }
}

🔍 关键点解析

  1. preSum[0] = 0 作为哨兵值,统一计算逻辑
  2. 数组索引从1开始,与天数自然对应
  3. 查询时注意right+1的边界处理

🚀 二维前缀和升级版

例题2:矩阵区域和(力扣304)

二维区域和检索 - 矩阵不可变

假设我们有如下矩阵:

复制代码
1 2 3
4 5 6
7 8 9

对应的二维前缀和矩阵:

java 复制代码
// 构造公式:
preSum[i][j] = preSum[i-1][j] 
             + preSum[i][j-1] 
             - preSum[i-1][j-1] 
             + matrix[i-1][j-1];

// 结果矩阵:
0  0  0  0
0  1  3  6
0  5 12 21
0 12 27 45

可视化推导

graph TD A[原点0,0] --> B[计算第一行] B --> C[逐行填充] C --> D[处理重叠区域]

Java实现

java 复制代码
class NumMatrix {
    private int[][] preSum;

    public NumMatrix(int[][] matrix) {
        int m = matrix.length, n = matrix[0].length;
        preSum = new int[m+1][n+1];
      
        for(int i=1; i<=m; i++){
            for(int j=1; j<=n; j++){
                preSum[i][j] = preSum[i-1][j] 
                             + preSum[i][j-1] 
                             - preSum[i-1][j-1] 
                             + matrix[i-1][j-1];
            }
        }
    }
  
    public int sumRegion(int row1, int col1, int row2, int col2) {
        return preSum[row2+1][col2+1] 
             - preSum[row1][col2+1] 
             - preSum[row2+1][col1] 
             + preSum[row1][col1];
    }
}

💡 高阶技巧:前缀和+哈希表

例题3:统计子数组(力扣560)

和为 K 的子数组

java 复制代码
class Solution {
    public int subarraySum(int[] nums, int k) {
        HashMap<Integer, Integer> map = new HashMap<>();
        map.put(0, 1); // 初始状态:前缀和为0出现1次
        int count = 0, preSum = 0;
      
        for(int num : nums){
            preSum += num;
            // 查找之前是否存在preSum - k
            if(map.containsKey(preSum - k)){
                count += map.get(preSum - k);
            }
            map.put(preSum, map.getOrDefault(preSum, 0) + 1);
        }
        return count;
    }
}

🔑 核心思想: 通过哈希表记录前缀和出现次数,将时间复杂度从O(n²)降到O(n)


📝 总结表格:不同场景的时空复杂度

场景 暴力法时间复杂度 前缀和优化后
一维区间查询 O(n) per query O(1)
二维矩阵查询 O(mn) O(1)
统计子数组 O(n²) O(n)

🛠️ 前缀和四步使用法

  1. 识别问题:是否涉及区间累加和?
  2. 构建preSum:注意初始化方式和索引偏移
  3. 推导公式:找出preSum之间的数学关系
  4. 处理边界:特别是二维场景的四个角点计算

🎯 现在尝试用前缀和解这道题吧:724. 寻找数组的中心下标

相关推荐
floret. 小花16 分钟前
Vue3 知识点总结 · 2026-03-20
前端·面试·electron·学习笔记·vue3
小璐资源网17 分钟前
从源码看ArrayList与LinkedList的性能差异
后端
紫丁香27 分钟前
Dify源码深度剖析3
后端·python·ai·flask·fastapi
IT_陈寒28 分钟前
JavaScript开发者必看:3个让代码效率翻倍的隐藏技巧
前端·人工智能·后端
希望永不加班34 分钟前
如何在 SpringBoot 里自定义 Spring MVC 配置
java·spring boot·后端·spring·mvc
Welcome_Back40 分钟前
SpringBoot后端开发测试全指南
spring boot·后端·log4j
大傻^1 小时前
Spring AI Alibaba MCP协议实战:模型上下文协议集成与工具调用
java·人工智能·后端·spring·elasticsearch·springaialibaba
Lzh编程小栈1 小时前
数据结构与算法——单链表超详解(C语言完整实现 + 面试高频题)
c语言·开发语言·面试
前端摸鱼匠1 小时前
面试题2:Transformer的Encoder、Decoder结构分别包含哪些核心组件?
人工智能·深度学习·ai·面试·职场和发展·transformer
稻草猫.1 小时前
MyBatis进阶:动态SQL与MyBatis Generator插件使用
java·数据库·后端·spring·mvc·mybatis