一、Problem
Given an array of integers arr and an integer target.
You have to find two non-overlapping sub-arrays of arr each with sum equal target. There can be multiple answers so you have to find an answer where the sum of the lengths of the two sub-arrays is minimum.
Return the minimum sum of the lengths of the two required sub-arrays, or return -1 if you cannot find such two sub-arrays.
Input: arr = [3,2,2,4,3], target = 3
Output: 2
Explanation: Only two sub-arrays have sum = 3 ([3] and [3]). The sum of their lengths is 2.
Constraints:
1 <= arr.length <= 10^5
1 <= arr[i] <= 1000
1 <= target <= 10^8
二、Solution
方法一:前缀和
- 用 map 记录前缀和的每一项出现的位置
- Q:如果找和为 tar 的子数组呢?
A:如果pre[i] - tar
在 map 的 keySet 中出现过,如果出现位置为 ,且当前位置为 ,则表明数组中存在一段长为 的且和为 tar 的子数组。 - Q:如何判断两个和为 tar 的子数组是否重叠?
A:第二长的子数组的左端点大于大于第一小的子数组的右端点。证明:第一短的子数组一定是第一个找到,第二长的子数组一定是第二个找到。
class Solution {
public int minSumOfLengths(int[] a, int tar) {
int n = a.length, INF = 0x3f3f3f3f, pre[] = new int[n+1];
Map<Integer, Integer> mp = new HashMap<>();
mp.put(0, 0);
for (int i = 1; i <= n; i++) {
pre[i] = pre[i-1] + a[i-1];
mp.put(pre[i], i);
}
int fir = INF, sec = INF, minR = 0;
for (int r = 1; r <= n; r++) {
int d = pre[r] - tar;
if (mp.containsKey(d)) {
int l = mp.get(d), len = Math.abs(r - l);
if (len < fir) {
minR = r;
sec = fir;
fir = len;
} else if (len < sec && l >= minR)
sec = len;
}
}
return fir != INF && sec != INF ? fir+sec : -1;
}
}
复杂度分析
- 时间复杂度:,
- 空间复杂度:,