1477. Find Two Non-overlapping Sub-arrays Each With Target Sum
SourceBiweekly Contest 28 Q3DifficultyMediumRating1850
Description
You are given an array of integers arr and an integer target.
You have to find two non-overlapping sub-arrays of arr each with a 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.
Example 1:
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.
Example 2:
Input: arr = [7,3,4,7], target = 7 Output: 2 Explanation: Although we have three non-overlapping sub-arrays of sum = 7 ([7], [3,4] and [7]), but we will choose the first and third sub-arrays as the sum of their lengths is 2.
Example 3:
Input: arr = [4,3,2,6,2,3,4], target = 6 Output: -1 Explanation: We have only one sub-array of sum = 6.
Constraints:
1 <= arr.length <= 1051 <= arr[i] <= 10001 <= target <= 108
Solutions
Solution 1: Hash Table + Prefix Sum + Dynamic Programming
Thinking
The straightforward approach is to enumerate every subarray that sums to \(target\) and pair them while checking overlap. With \(n \le 10^5\), the number of subarrays is quadratic, so this does not fit.
Once the right segment is fixed, the left one must lie entirely in the prefix before it, and only the shortest valid subarray in that prefix matters. We therefore need a running answer to "the shortest valid segment in the prefix so far".
All values are positive, so prefix sums are strictly increasing and unique. A hash map from prefix sum to index then finds, in constant time, the unique segment \([j+1,i]\) that ends at the current position and sums to \(target\).
We scan left to right while maintaining \(f[i]\), the shortest such subarray among the first \(i\) elements. When \([j+1,i]\) appears, add \(f[j]\) to the current length to update the answer, then set \(f[i]=\min(f[i-1], i-j)\). The left piece always comes from before the current segment, so the two never overlap.
We use a hash table \(d\) to record the index of each prefix sum, initially \(d[0]=0\).
Define \(f[i]\) as the minimum length of a subarray with sum equal to \(target\) among the first \(i\) elements. Initially, \(f[0]=\infty\) and \(ans=\infty\). Indices are \(1\)-based.
Iterate through \(\textit{arr}\). For the current position \(i\), first set \(f[i]=f[i-1]\) and accumulate the prefix sum \(s\). If \(s-\textit{target}\) exists in the hash table, let \(j=d[s-\textit{target}]\). Then the interval \([j+1,i]\) sums to \(target\) and has length \(i-j\). Update \(f[i]=\min(f[i], i-j)\), and update the answer with the best length on the left: \(ans=\min(ans, f[j]+i-j)\). Then store \(d[s]=i\).
Finally, if \(ans\) is greater than the array length, return \(-1\); otherwise, return \(ans\).
The time complexity is \(O(n)\), and the space complexity is \(O(n)\), where \(n\) is the length of \(\textit{arr}\).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |