引言
在算法的世界中,前缀和算法是一种解决数组相关问题的高效方法。它通过预先计算数组元素的累积和,从而在查询时能够快速得到答案。作为一名Java技术博主,唐叔今天将带大家深入了解前缀和的工作原理,以及它在解决实际问题中的强大之处。通过本文,你将学会如何运用前缀和来处理各种数组问题,并在LeetCode上的应用实例中,掌握其解题技巧。
前缀和算法概述
定义
前缀和(Prefix Sum)是一种常见的算法技巧,主要用于处理数组或序列的连续子区间求和问题。通过构建一个前缀和数组,我们可以快速查询任意连续区间的和,从而在一定程度上优化时间复杂度。
基本原理
假设有一个数组 arr
,其前缀和数组 prefix
定义如下:
-
prefix[i]
表示从数组起点到位置i
的元素之和。 -
因此,前缀和数组
prefix
可以定义为:prefixSum[i] = arr[0] + arr[1] + ... + arr[i]
计算任意区间和
计算任意区间和 arr[l] + arr[l+1] + ... + arr[r]
可以通过前缀和快速得到:arr[l] + arr[l + 1] + ... + arr[r] = prefix[r] - prefix[l - 1]
例子
假设有数组 arr = [1, 2, 3, 4, 5]
,构建前缀和数组 prefix
如下:
prefix[0] = 1
prefix[1] = 1 + 2 = 3
prefix[2] = 1 + 2 + 3 = 6
prefix[3] = 1 + 2 + 3 + 4 = 10
prefix[4] = 1 + 2 + 3 + 4 + 5 = 15
那么,求区间和 arr[1] + arr[2] + arr[3]
就可以通过前缀和数组计算: arr[1] + arr[2] + arr[3] = prefix[3] - prefix[0] = 10 - 1
实现步骤
使用前缀和解决问题的一般步骤如下:
- 「初始化前缀和数组」:创建一个与原数组长度相同的前缀和数组,并将
prefix[0]
初始化为arr[0]
。 - 「构建前缀和数组」:通过遍历原数组,计算每个位置的前缀和。
- 「查询区间和」:通过前缀和数组快速计算任意区间的和。
注意事项
- 「初始化」:确保
prefix[0]
正确初始化为arr[0]
,避免后续计算出错。 - 「边界条件」:处理边界条件时要特别小心,确保不会越界。
- 「空间复杂度」:前缀和数组需要额外的存储空间,但通常不会对整体性能产生太大影响。
应用场景
前缀和常用于解决以下问题:
- 快速计算数组任意区间的和。
- 确定数组中某个元素的累积和。
- 优化双指针问题。
LeetCode实战:前缀和算法应用
入门题:1480. 一维数组的动态和
题目链接:1480. 一维数组的动态和
题目描述:给你一个数组 nums
,返回其动态和 runningSum
,其中 runningSum[i] = sum(nums[0]…nums[i])
。
Java代码实现
class Solution {
public int[] runningSum(int[] nums) {
int n = nums.length;
int[] runningSum = new int[n];
runningSum[0] = nums[0];
for (int i = 1; i < n; i++) {
runningSum[i] = runningSum[i - 1] + nums[i];
}
return runningSum;
}
}
解题思路
这个问题可以直接通过前缀和来解决。我们遍历数组,逐步计算每个位置的前缀和,并将其存储在结果数组中。
中等题:560. 和为K的子数组
题目链接:560. 和为K的子数组
题目描述:给定一个整数数组 nums
和一个整数 k
,返回数组中和为 k
的连续子数组的个数。
Java代码实现
import java.util.HashMap;
import java.util.Map;
class Solution {
public int subarraySum(int[] nums, int k) {
Map prefixCount = new HashMap<>();
prefixCount.put(0, 1); // 初始化前缀和为0的情况
int prefix = 0;
int count = 0;
for (int num : nums) {
prefix += num;
if (prefixCount.containsKey(prefix - k)) {
count += prefixCount.get(prefix - k);
}
prefixCount.put(prefix, prefixCount.getOrDefault(prefix, 0) + 1);
}
return count;
}
}
解题思路
这个问题可以用前缀和结合哈希表来解决。我们遍历数组,计算每个位置的前缀和,并将前缀和存入哈希表中。对于每个前缀和 prefix
,检查哈希表中是否存在 prefix - k
,如果存在,则说明存在一个子数组的和为 k
。
更多LeetCode题目推荐
如果您对前缀和算法感兴趣,希望挑战更多题目,以下是一些LeetCode上推荐的题目:
- 303. 区域和检索 - 数组不可变
- 304. 二维区域和检索 - 矩阵不可变
- 523. 连续的子数组和
- 525. 连续数组
- 974. 和可被 K 整除的子数组
- 1248. 统计"优美子数组"
- 1281. 整数的各位积和
- 1356. 有多少小于当前数字的数字
结语
通过本文的学习,相信大家对前缀和算法有了更深入的理解。前缀和算法虽然简单,但在实际应用中却非常高效,特别是在处理数组区间求和问题时。希望各位读者朋友能够在实践中灵活运用前缀和算法,解决更多的编程问题。
如果有任何疑问或建议,欢迎在评论区留言交流!下次见!
希望这篇文章能够帮助大家更好地理解和应用前缀和算法。如果喜欢这篇文章,别忘了点赞和分享哦!😊