1477 LeetCode problem solution
LeetCode problem link: 1477. Find Two Non-overlapping Sub-arrays Each With Target Sum
LeetCode 1477 problem description
Medium level problem.
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]. Their total length is 2.
Example 2:
Input: arr = [7,3,4,7], target = 7
Output: 2
Explanation: We can choose [7] at the beginning and [7] at the end.
Example 3:
Input: arr = [4,3,2,6,2,3,4], target = 6
Output: -1
Constraints:
1 <= arr.length <= 10⁵1 <= arr[i] <= 10001 <= target <= 10⁸
LeetCode 1477 problem: solution explanation
We can solve this problem by using Sliding Window + Prefix Minimum patterns.
Because every value in arr is positive, we use a sliding window to find sub-arrays whose sum is exactly target.
At the same time, we store the minimum length of a valid sub-array found before each position. This allows us to combine the current valid sub-array with the shortest non-overlapping one found earlier.
Step 1: Find target-sum sub-arrays
Use two pointers:
left
rightand maintain the sum of the current window:
sum = arr[left] + ... + arr[right]For every right, add arr[right] to sum.
If:
sum > targetmove left forward and subtract elements until:
sum <= targetBecause all elements are positive, increasing right increases the sum and increasing left decreases it.
When:
sum == targetthe current sub-array [left, right] is valid and its length is:
right - left + 1Step 2: Store the shortest valid sub-array in each prefix
We use:
best[i]to store the minimum length of a target-sum sub-array that ends at or before index i.
If the current window [left, right] has sum equal to target, its length is:
len = right - left + 1We update:
minLen = min(minLen, len)
best[right] = minLenIf the current window is not valid, best[right] keeps the shortest valid length found earlier.
Step 3: Combine two non-overlapping sub-arrays
Suppose the current valid sub-array is:
[left, right]A non-overlapping previous sub-array must end before left.
Therefore, its shortest possible length is stored in:
best[left - 1]If it exists, combine the two lengths:
best[left - 1] + (right - left + 1)and update:
result = min(result, best[left - 1] + len)Because the previous sub-array ends at or before left - 1, the two sub-arrays cannot overlap.
Example
For:
arr = [3, 2, 2, 4, 3]
target = 3At index 0, the window:
[3]has sum 3, so:
best[0] = 1At index 4, we find another valid window:
[3]with:
left = 4
right = 4
len = 1The shortest valid sub-array before left is:
best[3] = 1Therefore:
result = 1 + 1
result = 2LeetCode 1477 problem: complexity
Each element is added to the sliding window once and removed at most once.
The best array is updated once for every index.
Time complexity: O(n)
Space complexity: O(n)
Pattern: Sliding Window
Technique: Two Pointers / Prefix Minimum
LeetCode 1477 C++ solution
class Solution {
public:
int minSumOfLengths(vector<int>& arr, int target)
{
int n = arr.size();
int INF = n + 1;
vector<int> best(n, INF);
int left = 0;
int sum = 0;
int minLen = INF;
int result = INF;
for(int right = 0; right < n; right++)
{
sum += arr[right];
while(sum > target)
{
sum -= arr[left];
left++;
}
if(sum == target)
{
int len = right - left + 1;
if(left > 0 && best[left - 1] != INF)
result = min(result, len + best[left - 1]);
minLen = min(minLen, len);
}
best[right] = minLen;
}
return result == INF ? -1 : result;
}
};LeetCode 1477 Java solution
class Solution {
public int minSumOfLengths(int[] arr, int target) {
int n = arr.length;
int INF = n + 1;
int[] best = new int[n];
Arrays.fill(best, INF);
int left = 0;
int sum = 0;
int minLen = INF;
int result = INF;
for(int right = 0; right < n; right++) {
sum += arr[right];
while(sum > target) {
sum -= arr[left];
left++;
}
if(sum == target) {
int len = right - left + 1;
if(left > 0 && best[left - 1] != INF)
result = Math.min(result, len + best[left - 1]);
minLen = Math.min(minLen, len);
}
best[right] = minLen;
}
return result == INF ? -1 : result;
}
}LeetCode 1477 JavaScript solution
var minSumOfLengths = function(arr, target) {
const n = arr.length;
const INF = n + 1;
const best = new Array(n).fill(INF);
let left = 0;
let sum = 0;
let minLen = INF;
let result = INF;
for(let right = 0; right < n; right++) {
sum += arr[right];
while(sum > target) {
sum -= arr[left];
left++;
}
if(sum === target) {
const len = right - left + 1;
if(left > 0 && best[left - 1] !== INF)
result = Math.min(result, len + best[left - 1]);
minLen = Math.min(minLen, len);
}
best[right] = minLen;
}
return result === INF ? -1 : result;
};LeetCode 1477 TypeScript solution
function minSumOfLengths(arr: number[], target: number): number {
const n: number = arr.length;
const INF: number = n + 1;
const best: number[] = new Array(n).fill(INF);
let left: number = 0;
let sum: number = 0;
let minLen: number = INF;
let result: number = INF;
for(let right = 0; right < n; right++) {
sum += arr[right];
while(sum > target) {
sum -= arr[left];
left++;
}
if(sum === target) {
const len: number = right - left + 1;
if(left > 0 && best[left - 1] !== INF)
result = Math.min(result, len + best[left - 1]);
minLen = Math.min(minLen, len);
}
best[right] = minLen;
}
return result === INF ? -1 : result;
}LeetCode 1477 Python solution
class Solution:
def minSumOfLengths(self, arr: List[int], target: int) -> int:
n = len(arr)
INF = n + 1
best = [INF] * n
left = 0
window_sum = 0
min_len = INF
result = INF
for right in range(n):
window_sum += arr[right]
while window_sum > target:
window_sum -= arr[left]
left += 1
if window_sum == target:
length = right - left + 1
if left > 0 and best[left - 1] != INF:
result = min(result, length + best[left - 1])
min_len = min(min_len, length)
best[right] = min_len
return -1 if result == INF else result