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

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

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

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


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

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

天数 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. 寻找数组的中心下标

相关推荐
uzong6 小时前
软件架构指南 Software Architecture Guide
后端
又是忙碌的一天6 小时前
SpringBoot 创建及登录、拦截器
java·spring boot·后端
勇哥java实战分享7 小时前
短信平台 Pro 版本 ,比开源版本更强大
后端
学历真的很重要7 小时前
LangChain V1.0 Context Engineering(上下文工程)详细指南
人工智能·后端·学习·语言模型·面试·职场和发展·langchain
计算机毕设VX:Fegn08957 小时前
计算机毕业设计|基于springboot + vue二手家电管理系统(源码+数据库+文档)
vue.js·spring boot·后端·课程设计
上进小菜猪8 小时前
基于 YOLOv8 的智能杂草检测识别实战 [目标检测完整源码]
后端
韩师傅8 小时前
前端开发消亡史:AI也无法掩盖没有设计创造力的真相
前端·人工智能·后端
栈与堆9 小时前
LeetCode-1-两数之和
java·数据结构·后端·python·算法·leetcode·rust
superman超哥9 小时前
双端迭代器(DoubleEndedIterator):Rust双向遍历的优雅实现
开发语言·后端·rust·双端迭代器·rust双向遍历
1二山似9 小时前
crmeb多商户启动swoole时报‘加密文件丢失’
后端·swoole