Indexes of Subarray Sum
Given an array arr[] containing only non-negative integers, your task is to find a continuous subarray (a contiguous sequence of elements) whose sum equals a specified value target
. You need to return the 1-based indices of the leftmost and rightmost elements of this subarray. You need to find the first subarray whose sum is equal to the target.
Note: If no such array is possible then, return [-1].
Examples:
Input: arr[] = [1, 2, 3, 7, 5], target = 12
Output: [2, 4]
Explanation: The sum of elements from 2nd to 4th position is 12.
Input: arr[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], target = 15
Output: [1, 5]
Explanation: The sum of elements from 1st to 5th position is 15.
Input: arr[] = [5, 3, 4], target = 2
Output: [-1]
Explanation: There is no subarray with sum 2.
Constraints:
1 <= arr.size()<= 106
0 <= arr[i] <= 103
0 <= target <= 109
To solve this problem efficiently, we can use a sliding window technique with the two-pointer approach. This is a very efficient way to find the subarray with a target sum in linear time, as it avoids checking all possible subarrays (which would be inefficient for large arrays).
Approach: Sliding Window (Two Pointers)
- Start with two pointers: Begin with both pointers (
start
andend
) at the start of the array. Theend
pointer will iterate over the array, and thestart
pointer will help in maintaining the subarray sum that matches the target. - Expand the window: As
end
moves forward, accumulate the sum of elements between thestart
andend
pointers. - Shrink the window if necessary: If the sum exceeds the target, increment the
start
pointer to reduce the sum. - Check for match: If at any point the sum equals the target, return the 1-based indices of the
start
andend
pointers. - Edge Case: If no subarray is found that matches the target, return
[-1]
.
Code Implementation:
public class Solution {
public int[] SubarraySum(int[] arr, int target) {
int n = arr.Length;
int start = 0, currentSum = 0;
for (int end = 0; end < n; end++) {
currentSum += arr[end];
// Shrink the window from the left if the sum exceeds target
while (currentSum > target && start <= end) {
currentSum -= arr[start];
start++;
}
// If current sum equals target, return the 1-based indices
if (currentSum == target) {
return new int[] { start + 1, end + 1 }; // 1-based index
}
}
// If no subarray found
return new int[] { -1 };
}
}
Explanation:
- Initialize
start
andcurrentSum
:start
is the left pointer of the window, andcurrentSum
keeps track of the sum of elements betweenstart
andend
. - Iterate through the array: The
end
pointer moves through each element, and we add the value tocurrentSum
. - Shrink the window if necessary: If
currentSum
exceeds the target, we increment thestart
pointer and subtract the value atstart
fromcurrentSum
to reduce the sum. - Check for a match: Whenever
currentSum
equals the target, we return the 1-based indices (start + 1
andend + 1
). - Return
[-1]
if no match is found: If the loop ends without finding a subarray whose sum equals the target, we return[-1]
.
Time Complexity:
- Time Complexity: , where
n
is the size of the array. Each element is processed at most twice (once when adding tocurrentSum
and once when removing fromcurrentSum
). - Space Complexity: because we are only using a few variables (
start
,currentSum
, etc.) and not using any extra space proportional to the input size.
Example Walkthrough:
Example 1:
- Input:
arr[] = [1, 2, 3, 7, 5]
, target =12
- Iteration steps:
start = 0, end = 0
, sum = 1start = 0, end = 1
, sum = 3start = 0, end = 2
, sum = 6start = 0, end = 3
, sum = 13 → shrink the window (start = 1
)start = 1, end = 3
, sum = 12 → found the subarray.
- Output:
[2, 4]
(1-based indices).
Example 2:
- Input:
arr[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
, target =15
- Iteration steps:
start = 0, end = 4
, sum = 15 → found the subarray.
- Output:
[1, 5]
(1-based indices).
Example 3:
- Input:
arr[] = [5, 3, 4]
, target =2
- No subarray with sum 2.
- Output:
[-1]
.
This approach is optimal and ensures that we efficiently find the required subarray in linear time.