一维静态前缀和

一维静态前缀和

一维静态前缀和是一种预处理技术,用于快速计算数组中任意区间的元素和。
通过预先计算从数组起始位置到每个位置的累加和,可以将区间求和的时间复杂度从 优化到

基本概念

前缀和的核心思想是:

  1. 预处理数组,计算前缀和数组
  2. 前缀和数组的第个元素表示原数组前个元素的和
  3. 任意区间的和可以通过 得到
  4. 适用于频繁查询区间和的场景

实现方式

前缀和的实现步骤:

  1. 创建前缀和数组(通常比原数组多一个位置)
  2. 预处理计算前缀和
  3. 使用前缀和数组进行区间查询

基本实现

class PrefixSum {
private:
    vector<int> prefix;

public:
    PrefixSum(vector<int>& nums) {
        int n = nums.size();
        prefix.resize(n + 1);
        // 计算前缀和
        for (int i = 0; i < n; i++) {
            prefix[i + 1] = prefix[i] + nums[i];
        }
    }
    
    // 查询区间[left, right]的和
    int rangeSum(int left, int right) {
        return prefix[right + 1] - prefix[left];
    }
};
class PrefixSum {
    private int[] prefix;
    
    public PrefixSum(int[] nums) {
        int n = nums.length;
        prefix = new int[n + 1];
        // 计算前缀和
        for (int i = 0; i < n; i++) {
            prefix[i + 1] = prefix[i] + nums[i];
        }
    }
    
    // 查询区间[left, right]的和
    public int rangeSum(int left, int right) {
        return prefix[right + 1] - prefix[left];
    }
}
class PrefixSum:
    def __init__(self, nums):
        n = len(nums)
        self.prefix = [0] * (n + 1)
        # 计算前缀和
        for i in range(n):
            self.prefix[i + 1] = self.prefix[i] + nums[i]
    
    # 查询区间[left, right]的和
    def range_sum(self, left, right):
        return self.prefix[right + 1] - self.prefix[left]

应用场景

前缀和在很多问题中都有应用:

  1. 区间和查询
  2. 统计子数组特征
  3. 优化动态规划
  4. 处理差分数组
  5. 二维前缀和的基础

示例:和为k的子数组个数

int subarraySum(vector<int>& nums, int k) {
    unordered_map<int, int> count;
    count[0] = 1;
    int sum = 0, result = 0;
    
    for (int num : nums) {
        sum += num;
        if (count.find(sum - k) != count.end()) {
            result += count[sum - k];
        }
        count[sum]++;
    }
    
    return result;
}
public int subarraySum(int[] nums, int k) {
    Map<Integer, Integer> count = new HashMap<>();
    count.put(0, 1);
    int sum = 0, result = 0;
    
    for (int num : nums) {
        sum += num;
        if (count.containsKey(sum - k)) {
            result += count.get(sum - k);
        }
        count.put(sum, count.getOrDefault(sum, 0) + 1);
    }
    
    return result;
}
def subarray_sum(nums, k):
    count = {0: 1}
    sum = result = 0
    
    for num in nums:
        sum += num
        if sum - k in count:
            result += count[sum - k]
        count[sum] = count.get(sum, 0) + 1
    
    return result

时间复杂度

  • 预处理:
  • 查询:
  • 空间复杂度:

前缀和的优缺点

优点:

  1. 区间查询时间复杂度
  2. 实现简单
  3. 可以扩展到二维

缺点:

  1. 只适用于静态数组
  2. 需要额外空间
  3. 不支持修改操作

注意事项

  1. 数组下标要正确处理
  2. 注意前缀和数组的大小
  3. 处理整数溢出问题
  4. 考虑空数组的边界情况

练习建议

  1. 实现基本的前缀和查询
  2. 解决子数组和相关问题
  3. 尝试结合其他技巧(如哈希表)
  4. 练习二维前缀和的应用

经典例题

  1. 【模板】前缀和
  2. 买卖股票的最好时机(一)
牛客代码笔记-牛栋 文章被收录于专栏

汗牛充栋,学海无涯。<br/> 内含算法知识点讲解,以及牛客题库精选例题。<br/> 学习算法,从牛栋开始。

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务