虽然之前在Sliding Window那篇小结里总结了一些关于subarray sum的题目,但总觉得还不够系统所以打算花更大的篇幅对leetcode中涉及到subarray sum的题目做一个小结。
1. 求subarray sum的最大值
53 Maximum Subarray:一道非常经典的dp题,这里就不作总结了
2. 求满足条件的subarray sum的个数
560. Subarray Sum Equals K:
求subarray sum等于K的subarray的个数,这里用HashMap记录每个前缀和的个数,和元素的正负无关。
那如果不是要求相等,而是要求>=或<=K的个数呢(当然>或<也是一样的,这里仅用>=和<=做例子)?
(1)如果所有元素均为正数:
印象中并未在leetcode中见过完全一样的题目,不过应该有一些类似的题目。总而言之都是用sliding window来处理,复杂度:O(N) O(1)。既然leetcode中没找到,那就自己写吧:
求一个正数数组中>=K的subarray sum的个数
public int countSubarray(int[] nums, int k) {
for int count = 0, sum = 0, l = 0;
for (int r = 0; r < nums.length; r ++) {
sum += nums[r];
while (sum >= K)
sum -= nums[l++];
count += l;
}
return count;
}
求一个正数数组中<=K的subarray sum的个数
public int countSubarray(int[] nums, int k) {
int count = 0, sum = 0, l = 0;
for (int r = 0; r < nums.length; r ++) {
sum += nums[r];
while (sum > k)
sum -= nums[l++];
count += r - l + 1;
}
return count;
}
(2)如果去掉均为正数的限制,数组中正负数都有可能出现
327. Count of Range Sum
和之前的题目相比,难度陡增,这道题merge sort/BIT/Segment Tree都可以解决,本质都是divide and conquer。复杂度:O(NlogN) O(1)个人更倾向于merge sort的解法(其实是因为对BIT/Segment Tree用得不熟)
3.求满足条件的subarray sum的最短/最长length
用hashmap记录prefix sum和index的关系,index是该prefix sum首次出现的位置。如果题目改成minimum size subarray sum equals k,那么hashmap中就改成记录index最近出现的位置。这道题同样和正负无关
非相等情况:
(1)如果元素均为正数
求一个正数数组中subarray sum >= k的最小长度
求一个正数数组中subarray sum <= k的最大长度
public int maxLength(int[] nums, int k) {
int sum = 0, max = 0, l = 0;
for (int r = 0; r < nums.length; i ++) {
sum += nums[r];
while (sum > k)
sum -= nums[l++];
max = Math.max(r-l+1, max);
}
return max;
}
(2) 如果元素可能存在负数
862. Shortest Subarray with Sum at Least K
难度提高一个档次,用sliding window + monotonic queue解决
如果题目改成shortest + at most k,longest + at least k, longest + at most k貌似都不可用上述方法解。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。