Array · 8 of 36
Find if there is any subarray with sum equal to 0
Check if some unbroken stretch of the array adds up to exactly zero, by watching for a running total you have seen before.
- Simple way
- time O(n^2)
room O(1) - Clever way
- time O(n)
room O(n)
The problem, simply
You get an array of whole numbers, some may be negative. Is there a stretch of boxes next to each other (a subarray) whose numbers add up to exactly 0? Answer true or false.
The stretch can be any length from one box to the whole array.
A story to remember it
Picture it
The boxes 2, -3 and 1 add up to 0. Running totals: 4, 6, 3, 4. The total 4 shows up twice, and the boxes between the two 4s are the zero stretch.
- answer
Examples
A normal case
- In
[4, 2, -3, 1, 6]- Out
true
2 + (-3) + 1 = 0.
A single zero
- In
[4, 2, 0, 1, 6]- Out
true
A stretch of one box holding 0 counts.
The stretch starts at the very beginning
- In
[3, -1, -2, 5]- Out
true
3 - 1 - 2 = 0. The running total comes back to 0, the height we started at. This is why the notebook starts with 0 already written.
No zero stretch
- In
[-3, 2, 3, 1, 6]- Out
false
Running totals: -3, -1, 2, 3, 9. They are all different and none is 0.
Way 1: the simple way
Try every start. From each start, keep adding boxes to the right and check if the total hits 0.
- For each start
i, setsum = 0. - For each end
jfromion, addarr[j]. Ifsum == 0, return true. - If nothing hits 0, return false.
class Solution {
public boolean hasZeroSum(int[] arr) {
for (int i = 0; i < arr.length; i++) { // start of the stretch
int sum = 0;
for (int j = i; j < arr.length; j++) { // grow it one box at a time
sum += arr[j];
if (sum == 0) return true;
}
}
return false;
}
}How long it takes: about n * n / 2 stretches, O(n^2). Extra room: one total, O(1).
Way 2: the clever way
Keep a running total, called the prefix sum. If the total after box j equals the total after an earlier box i, then the boxes i + 1 to j added nothing, so they sum to 0.
- Put 0 in a notebook (a hash set) first. It stands for "before any box".
- Walk the array and add each number to
sum. - If
sumis already in the notebook, return true. - Otherwise write
sumin the notebook and move on.
The animation keeps the box number next to each total, so you can see which stretch it is.
Write down every running total and watch for a repeat
01 / 05
Before any box, our running total (the height) is 0. Write 0 in the notebook, marked as the start.
- sum
- 0
- looking now
- answer
- just added
class Solution {
public boolean hasZeroSum(int[] arr) {
Map<Long, Integer> seen = new HashMap<>(); // running total -> box after which we saw it
seen.put(0L, -1); // height 0 before any box
long sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
Integer before = seen.get(sum);
if (before != null) {
// boxes before + 1 .. i add up to 0
return true;
}
seen.put(sum, i);
}
return false;
}
}How long it takes: one walk with one notebook check per box, O(n) on average. Extra room: up to n + 1 totals in the notebook, O(n).
Watch out for
- Running totals can overflow an
intwhen the numbers are large. Alongtotal is safer. - Store the first box where each total appeared, and do not overwrite it. That gives the longest zero stretch if you need it.
- Sorting the array does not help: it destroys which boxes are next to each other.
What interviewers ask next
- Return the stretch itself. The map already knows: it is from
before + 1toi. - Longest stretch with sum 0? Keep the first box of each total and take the biggest
i - before. - How many stretches sum to 0? Store how many times each total has appeared, and add that count every time you see it again.
- Stretches that sum to
kinstead of 0? Look upsum - kinstead ofsum. SameO(n)idea. - What if all numbers are positive? Then totals only grow, so no repeat is possible unless there is a 0 in the array. For "sum to k" with positive numbers a sliding window works with
O(1)extra room.
Remember this
Grown-up words: the height after each step is a prefix sum, the notebook is a hash set (or a hash map from sum to index), and a stretch of boxes next to each other is a subarray.