Subarray of Given Sum II in O(n) Time Complexity using C++


Given an array of non-negative integers and a number target, find a continous subarray whose sum is equal to target.

Return the start and end indices denoting this subarray.

If there are multiple solutions, you can return any of them.


Example:

Input: nums = [1, 1, 5, 2, 1, 3, 10, 2, 1], k = 21
Output: [2, 6]
Explanation: 5 + 2 + 1 + 3 + 10 = 21

Note:

1. The input array contains only non-negative integers.

2. Your algorithm should run in O(n) time and use O(1) extra space.


Understanding the Problem

The core challenge of this problem is to find a continuous subarray within a given array of non-negative integers that sums up to a specified target value. This problem is significant in various applications such as financial analysis, where one might need to find a period with a specific sum of transactions.

Potential pitfalls include misunderstanding the requirement for a continuous subarray and not considering the constraints of O(n) time complexity and O(1) extra space.

Approach

To solve this problem, we can use the sliding window technique. This approach involves maintaining a window that expands and contracts to find the subarray that sums to the target value.

1. **Naive Solution**: A naive solution would involve checking all possible subarrays and their sums, which would result in O(n^2) time complexity. This is not optimal for large arrays.

2. **Optimized Solution**: The sliding window technique allows us to achieve O(n) time complexity by maintaining a running sum and adjusting the window's start and end indices accordingly.

Algorithm

1. Initialize two pointers, `start` and `end`, both set to 0, and a variable `current_sum` set to 0.

2. Iterate through the array using the `end` pointer, adding the current element to `current_sum`.

3. If `current_sum` exceeds the target, increment the `start` pointer and subtract the element at the `start` pointer from `current_sum` until `current_sum` is less than or equal to the target.

4. If `current_sum` equals the target, return the indices `[start, end]`.

Code Implementation


#include <iostream>
#include <vector>

std::vector<int> subarraySum(std::vector<int>& nums, int target) {
    int start = 0, current_sum = 0;
    for (int end = 0; end < nums.size(); ++end) {
        // Add the current element to the running sum
        current_sum += nums[end];
        
        // While the current sum exceeds the target, move the start pointer to the right
        while (current_sum > target && start <= end) {
            current_sum -= nums[start];
            ++start;
        }
        
        // If the current sum equals the target, return the start and end indices
        if (current_sum == target) {
            return {start, end};
        }
    }
    // Return an empty vector if no subarray is found
    return {};
}

int main() {
    std::vector<int> nums = {1, 1, 5, 2, 1, 3, 10, 2, 1};
    int target = 21;
    std::vector<int> result = subarraySum(nums, target);
    if (!result.empty()) {
        std::cout << "Subarray found from index " << result[0] << " to " << result[1] << std::endl;
    } else {
        std::cout << "No subarray found" << std::endl;
    }
    return 0;
}

Complexity Analysis

The time complexity of this approach is O(n) because each element is processed at most twice (once when added and once when subtracted). The space complexity is O(1) as we are using only a few extra variables.

Edge Cases

1. **Empty Array**: If the input array is empty, the function should return an empty vector.

2. **Single Element**: If the array contains a single element equal to the target, the function should return the indices [0, 0].

3. **No Valid Subarray**: If no subarray sums to the target, the function should return an empty vector.

Testing

To test the solution comprehensively, consider the following test cases:

  • Simple cases with small arrays.
  • Edge cases such as empty arrays and single-element arrays.
  • Cases where multiple subarrays sum to the target.
  • Large arrays to ensure the solution handles them efficiently.

Thinking and Problem-Solving Tips

When approaching such problems, it is crucial to:

  • Understand the problem requirements and constraints thoroughly.
  • Consider different approaches and their trade-offs.
  • Break down the problem into smaller, manageable parts.
  • Practice similar problems to improve problem-solving skills.

Conclusion

In this blog post, we discussed how to find a continuous subarray that sums to a given target using the sliding window technique. We provided a detailed explanation of the approach, algorithm, and code implementation in C++. Understanding and solving such problems is essential for developing strong problem-solving skills in programming.

Additional Resources

For further reading and practice, consider the following resources: