GeeksforGeeks Medium

Longest Subarray with Sum K

Longest Subarray with Sum K is a GFG problem (LeetCode has it as premium problem 325, Maximum Size Subarray Sum Equals k). You are given an integer array arr and an integer k. Return the length of the longest subarray whose elements add up to exactly k, or 0 if there is none.

  • A subarray is a contiguous run of elements.
  • The array may contain negative numbers and zeros. That one detail decides the whole approach.
  • n can be 10⁵, so checking all n² subarrays is too slow; the target is one pass.
Constraints
  • 1 <= n <= 10⁵
  • -10⁵ <= nums[i] <= 10⁵
  • -10⁹ <= k <= 10⁹
  • Negative values are allowed, so a shrinking window will not work
arrayprefix-sumhash-table
Open on GeeksforGeeks ↗
02

Intuition

Finding the longest subarray with given sum k directly means checking every pair (start, end), which is O(n²). A prefix sum cuts it to one pass.

Let prefix[i] be the sum of arr[0..i]. Then

sum(arr[j+1..i]) = prefix[i] - prefix[j]

so a subarray ending at i sums to k exactly when some earlier prefix equals prefix[i] - k. The question "which start works?" becomes a single hash-map lookup, and the map only needs to remember where each prefix value first appeared.

How to spot this pattern

"Subarray" plus "sum equals k" plus negative numbers allowed means prefix sums with a hash map. If every number were positive, a sliding window would do the same job in O(1) space, because growing the window could only raise the sum. Negatives break that, so the window has no rule for which end to move.

03

Approach

Try it first

Before reading on: write sum(arr[j+1..i]) in terms of two prefix sums. Then decide what the hash map should store for the longest subarray, and what it must contain before the loop starts.

1

Seed the map

first = {0: -1}, prefix = 0, best = 0. The 0 → -1 entry stands for the empty prefix before index 0, so a subarray that starts at index 0 can be found too.

2

Extend the prefix sum

For each index i, add arr[i] to prefix. It now holds the sum of arr[0..i]. One running total replaces recomputing each subarray's sum, which is what makes the pass O(n).

3

Look up the partner prefix

If prefix - k is in the map at index j, then arr[j+1..i] sums to k and has length i - j. Update best with it. A subarray ending at i sums to k exactly when an earlier prefix equals prefix - k, so one lookup checks every possible start at once. Look it up before storing the current prefix, so with k = 0 an index can never match itself.

4

Store the prefix only if it is new

If prefix is not in the map, store first[prefix] = i. Never overwrite an existing entry. The earliest index of a prefix value gives the longest subarray, so later repeats are never better.

5

Return best

After one pass, best is the longest length found, or 0 if no lookup ever succeeded. Every subarray ends at some index, and each ending index was checked once with its best start.

04

Longest Subarray with Sum K solution in Python | C++ | Java

▶1class Solution:
▶2 def longestSubarray(self, arr: List[int], k: int) -> int:
▶3 first = {0: -1}
▶4 prefix = 0
▶5 best = 0
▶6 for i, x in enumerate(arr):
▶7 prefix += x
▶8 if prefix - k in first:
▶9 best = max(best, i - first[prefix - k])
▶10 if prefix not in first:
▶11 first[prefix] = i
▶12 return best
arrprefix1005122731495first0 → -1lookupprefix − k15k0bestseed 0 → -1, then one pass
first{0: -1}prefix value → first index
k15target sum
best0longest length so far
Idea. sum(arr[j+1..i]) = prefix[i] - prefix[j]. So at each index, ask the map whether the value prefix - k appeared earlier. The seed {0: -1} is the empty prefix, so a subarray starting at index 0 can be found too.
arrprefix100105122731495first0 → -110 → 0lookup-5prefix − k15k0best-5 not in map · store 10 → 0
i0arr[i] = 10
prefix10sum of arr[0..0]
prefix - k-5not seen
best0none yet
No earlier prefix equals -5, so no subarray ending at index 0 sums to 15. Store 10 → 0 so later indices can use it as a start point.
length 2arrprefix10010511522731495first0 → -110 → 015 → 1lookup0prefix − k15k2bestfound → best = 2 · store 15 → 1
i1arr[i] = 5
prefix15sum of arr[0..1]
prefix - k0found at -1
best2arr[0..1]
The map has 0 at index -1, so the elements after it, arr[0..1], add up to exactly 15. Its length is 1 + 1 = 2, the best so far. Store 15 → 1 so later indices can use it as a start point.
arrprefix1001051152217731495first0 → -110 → 015 → 117 → 2lookup2prefix − k15k2best2 not in map · store 17 → 2
i2arr[i] = 2
prefix17sum of arr[0..2]
prefix - k2not seen
best2arr[0..1]
No earlier prefix equals 2, so no subarray ending at index 2 sums to 15. Store 17 → 2 so later indices can use it as a start point.
arrprefix100105115221773241495first0 → -110 → 015 → 117 → 224 → 3lookup9prefix − k15k2best9 not in map · store 24 → 3
i3arr[i] = 7
prefix24sum of arr[0..3]
prefix - k9not seen
best2arr[0..1]
No earlier prefix equals 9, so no subarray ending at index 3 sums to 15. Store 24 → 3 so later indices can use it as a start point.
length 4arrprefix10010511522177324142595first0 → -110 → 015 → 117 → 224 → 325 → 4lookup10prefix − k15k4bestfound → best = 4 · store 25 → 4
i4arr[i] = 1
prefix25sum of arr[0..4]
prefix - k10found at 0
best4arr[1..4]
The map has 10 at index 0, so the elements after it, arr[1..4], add up to exactly 15. Its length is 4 - 0 = 4, the best so far. Store 25 → 4 so later indices can use it as a start point.
arrprefix1001051152217732414259534first0 → -110 → 015 → 117 → 224 → 325 → 434 → 5lookup19prefix − k15k4best19 not in map · store 34 → 5
i5arr[i] = 9
prefix34sum of arr[0..5]
prefix - k19not seen
best4arr[1..4]
No earlier prefix equals 19, so no subarray ending at index 5 sums to 15. Store 34 → 5 so later indices can use it as a start point.
longest, length 4arrprefix1001051152217732414259534first0 → -110 → 015 → 117 → 224 → 325 → 434 → 5lookupprefix − k15k4bestreturn 4
best4length of arr[1..4]
Done in one pass. The longest subarray summing to 15 is [5, 2, 7, 1], length 4. Every index did one lookup and at most one insert, so the whole scan is O(n).
05

Brute force over every start

For each start index the inner loop grows the subarray one element at a time, keeping its sum in total, so every subarray is summed in O(1) extra work.

▶1class Solution:
▶2 def longestSubarray(self, arr: List[int], k: int) -> int:
▶3 best = 0
▶4 for i in range(len(arr)):
▶5 total = 0
▶6 for j in range(i, len(arr)):
▶7 total += arr[j]
▶8 if total == k:
▶9 best = max(best, j - i + 1)
▶10 return best
06

Common pitfalls

Using a sliding window when negatives are allowed

✗ Wrong
while window_sum > k:
    window_sum -= arr[lo]
    lo += 1
✓ Right
if prefix - k in first:
    best = max(best, i - first[prefix - k])

Shrinking on overshoot assumes that dropping an element lowers the sum. For [1, -1, 5, -2, 3] and k = 3, dropping -1 raises it, so the window throws away the start of the answer [1, -1, 5, -2] and returns 0 instead of 4.

Overwriting the index of a repeated prefix

✗ Wrong
first[prefix] = i
✓ Right
if prefix not in first:
    first[prefix] = i

In [-1, 1, 1] with k = 1 the prefix 0 appears at the seed (-1) and again at index 1. Overwriting moves it to 1, so the final lookup gives length 1 instead of 3.

Forgetting the {0: -1} seed

✗ Wrong
first = {}
✓ Right
first = {0: -1}

A subarray that starts at index 0 needs the empty prefix as its partner. For [3, 1] and k = 4 the only answer is the whole array, and without the seed the result is 0.

07

Edge cases

Sums beyond 32 bits

With n = 10⁵ and values up to 10⁵ in size, prefix sums can reach 10¹⁰. C++ and Java keep prefix and the map keys as 64-bit.

08

Complexity

Time
O(n)
Space
O(n)
The longest subarray with sum k Python code (and the C++ and Java versions) makes one pass with O(1) average hash-map work per element. The map holds at most n + 1 distinct prefix values. Checking every subarray directly would be O(n²).
09

Longest vs count, negatives vs positives

Three problems that look alike; the values and the question decide the tool.

ProblemValuesMethodMap stores
Longest subarray with sum kany, including negativesprefix sum + hash mapfirst index of each prefix
Longest subarray with sum kall positivesliding window, O(1) spacenothing
Count subarrays with sum k (LeetCode 560)anyprefix sum + hash maphow many times each prefix occurred
10

Longest Subarray with Sum K FAQ

How do you find the longest subarray with sum k?
  • Idea: sum(arr[j+1..i]) = prefix[i] - prefix[j], so look for an earlier prefix equal to prefix[i] - k.
  • Map: prefix value → first index where it appeared, seeded with {0: -1}.
  • Loop: add arr[i] to prefix; if prefix - k is in the map at j, update best with i - j; store prefix only if it is new.
  • Complexity: O(n) time, O(n) space.
  • Example: [10, 5, 2, 7, 1, 9], k = 15 gives 4 for [5, 2, 7, 1].
Is there a longest subarray with sum k LeetCode problem?

Yes, as LeetCode 325, Maximum Size Subarray Sum Equals k, which is a premium problem. LeetCode 560, Subarray Sum Equals K, is the free counting version: the same prefix-sum idea, but the map stores counts.