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

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

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

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


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

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

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

相关推荐
weixin_438335402 小时前
springboot使用阿里云OSS实现文件上传
spring boot·后端·阿里云
蓝婷儿2 小时前
前端面试每日三题 - Day 28
前端·面试·职场和发展
咸鱼睡不醒_3 小时前
SpringBoot项目接入DeepSeek
java·spring boot·后端
yi念zhi间4 小时前
如何把ASP.NET Core WebApi打造成Mcp Server
后端·ai·mcp
声声codeGrandMaster4 小时前
Django之账号登录及权限管理
后端·python·django
码傻啦弟4 小时前
常用设计模式在 Spring Boot 项目中的实战案例
java·spring boot·后端·设计模式
南玖yy4 小时前
C++ 工具链与开发实践:构建安全、高效与创新的开发生态
开发语言·c++·人工智能·后端·安全·架构·交互
机器视觉知识推荐、就业指导5 小时前
Qt/C++面试【速通笔记七】—Qt中为什么new QWidget不需要手动调用delete?
c++·qt·面试
溟洵5 小时前
【C++ Qt】多元素控件(ListWidget、TableWidget、TreeWidget)
开发语言·前端·c++·后端·qt