前缀和
本人没有算法基础,以下均为春招刷Leetcode的笔记,仅用于记录,侵权勿喷
前缀和本质是一种预积分手段,运行时只需要得到边界值,就能快速、无损地获得区间积分值,二维的前缀和SAT在图形学中也有重要的运用
- 注意数组越界,尤其是前缀乘
- 明确索引的含义,这关系着数组的长度是否需要+1
- 前缀和可以使用哈希表加速查找
除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。
题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。
请不要使用除法,且在 O(n) 时间复杂度内完成此题。
特点
使用左右两个前缀和
思路
最简单的方法自然是求所有数的总乘积,
ans[i] = total / nums[i]
,不过这道题让我们不要用除法(如果数中有0,这种做法也是错的)
-
我们从左做一次前缀乘,
left[i]
表示以0~i
的前缀乘,从右开始做一次前缀乘,right[i]
表示以i~n-1
的前缀乘 -
ans[i]
将数组切分为三个部分,他自己,左边和右边,左边等于0~i-1
的总乘积,右边等于i+1~n-1
的总乘积,左右相乘即可得到最终结果 -
对于边界做特殊处理
实现
vector<int> productExceptSelf(vector<int>& nums) { |
和为k的子数组
给你一个整数数组
nums
和一个整数k
,请你统计并返回 该数组中和为k
的连续子数组的个数
-1000 <= nums[i] <= 1000
特点
数组有正有负,因此前缀和不递增
思路
固定右端点,向左找左端点,若存在和为k
的连续子数组,我们能找到一个左端点,使得左右端点前缀和之差为k
由于数组中包含负数,因此左端点可能有多个
于是问题转化为从右端点出发,寻找值为ps[j] - k
的左端点
当遍历完i
后,当前右端点preSum[i]
未来也可能是左端点,于是加入哈希表中
实现
int subarraySum(vector<int>& nums, int k) { |