Given an array of integers nums
and an integer k
, return the total number of subarrays whose sum equals to k
.
A subarray is a contiguous non-empty sequence of elements within an array.
For example:
nums = [1,1,1], k = 2
should return 2
because the subarrays [1, 1]
and [1, 1]
both sum to 2
.nums = [1,2,3], k = 3
should return 2
because [1, 2]
and [3]
sum to 3
.What is the most efficient algorithm in terms of time complexity to solve this problem? Please breakdown the time and space complexity of your solution. Be sure to think of any edge cases.
The most straightforward approach is to check every possible subarray and see if its sum equals k
. We can iterate through all possible start indices and, for each start index, iterate through all possible end indices to form subarrays. The sum of each subarray is computed, and if it matches k
, we increment the count.
def subarray_sum_brute_force(nums, k):
count = 0
for i in range(len(nums)):
for j in range(i, len(nums)):
subarray_sum = 0
for l in range(i, j + 1):
subarray_sum += nums[l]
if subarray_sum == k:
count += 1
return count
O(n^3) due to the three nested loops, where n is the length of the input array.
O(1) as we only use a constant amount of extra space.
A more efficient approach involves using a hashmap to store the prefix sums and their frequencies. The idea is that if prefix_sum[i] - prefix_sum[j] == k
, then the subarray from j+1
to i
has a sum of k
. We iterate through the array, maintaining the current prefix sum. For each prefix sum, we check if prefix_sum - k
exists in the hashmap. If it does, it means there's a subarray ending at the current index with a sum of k
. We increment our count by the frequency of prefix_sum - k
in the hashmap.
def subarray_sum_optimal(nums, k):
count = 0
prefix_sums = {0: 1}
current_sum = 0
for num in nums:
current_sum += num
if current_sum - k in prefix_sums:
count += prefix_sums[current_sum - k]
if current_sum in prefix_sums:
prefix_sums[current_sum] += 1
else:
prefix_sums[current_sum] = 1
return count
O(n), where n is the length of the input array, as we iterate through the array only once.
O(n) in the worst case, as the hashmap prefix_sums
can store up to n distinct prefix sums.
k
.