题记
穷则前缀哈希
达则滑动窗口
---鲁迅
前缀哈希
560. 和为K的子数组(统计子数组个数)
因为没有正整数的约束,无法用滑窗
前缀和 + hash表
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
mp=collections.defaultdict(int)
mp[0]=1
pre=0
count=0
for num in nums:
pre+=num
if pre-k in mp:
count+=mp[pre-k]
mp[pre]+=1
return count
325. 和等于 k 的最长子数组长度(统计子数组最大长度)
class Solution:
def maxSubArrayLen(self, nums: List[int], k: int) -> int:
n=len(nums)
# 上题存个数,这题存下标
pre_idx = defaultdict(int)
res=0
pre=0
# 忘了写这个
pre_idx[0] = -1
for i in range(n):
pre+=nums[i]
if pre not in pre_idx:
pre_idx[pre]=i
if pre-k in pre_idx:
res=max(res, i-pre_idx[pre-k])
return res
523. 连续的子数组和
有空看
滑动窗口
209. 长度最小的子数组
有正整数的约束,用滑窗, O ( n ) O(n) O(n)
但也可以用前缀和+二分, O ( n log n ) O(n\log n) O(nlogn)
class Solution {
public:
int minSubArrayLen(int target, vector<int> &nums) {
int sum = 0, l = 0, sz = nums.size() + 1;
for (int r = 0; r < nums.size(); ++r) {
sum += nums[r];
while (sum >= target) {
int cur_sz = r - l + 1;
if (cur_sz < sz) sz = cur_sz;
sum -= nums[l++];
}
}
return sz == nums.size() + 1 ? 0 : sz;
}
};