Array Problems Look Easy. These Six Coding Interview Bugs Disagree.

- Kadane's zero-init bug: initialize
max_sumandcurrent_sumtonums[0], not0; all-negative arrays return a valid element instead of a wrong zero - Prefix sum map needs two fixes: seed with
{0: 1}before the loop, and always look upprefix - kbefore updating the map, not after - Two pointers assume sorted input: sorting destroys original indices, so vanilla Two Sum requires a hash map, not converging pointers
- Sliding window shrink condition: use
>=not>for inclusive thresholds, and always undo accumulated state before advancing the left pointer - Python
inon lists is O(n): use asetfor membership andcollections.dequefor front removal to avoid hidden O(n²) inside your loop - 3Sum needs three deduplication guards: one on the outer loop with an
i > 0check, one on left after a match, one on right after a match
You finish the Two Sum warm-up. You nail the sliding window explanation. You feel genuinely good about arrays. Then the interviewer adds one edge case, your solution spits out the wrong number, and you spend the remaining ten minutes hunting a bug that isn't in your algorithm at all.
These bugs come from a short, repeating list of mistakes. They look correct. They pass every example you run. They fail quietly on inputs you haven't thought to test. The interviewer, meanwhile, is writing something down.
Here are the six responsible for most of the damage.

Arrays: humbling since 1958.
Your Kadane's Initializes to Zero (It Shouldn't)
This is the most common Kadane's bug, and it's invisible on the standard test cases.
You implement it like this:
max_sum = 0 current_sum = 0 for num in nums: current_sum = max(current_sum + num, 0) max_sum = max(max_sum, current_sum) return max_sum
Hand it [-3, -2, -5, -1]. Every element is negative, so current_sum resets to 0 on every iteration. The algorithm returns 0. The correct answer is -1. The interviewer makes a note.
The problem asks for the maximum sum subarray of at least one element. An empty subarray with sum zero isn't valid. Initializing to 0 silently treats the empty subarray as a candidate.
The fix is to initialize to the first element and reset to the current element rather than to zero:
max_sum = nums[0] current_sum = nums[0] for num in nums[1:]: current_sum = max(current_sum + num, num) max_sum = max(max_sum, current_sum) return max_sum
max(current_sum + num, num) asks: is it better to extend the current subarray, or start fresh from here? Starting fresh means starting at num, not at 0. This handles all-negative arrays correctly and doesn't change behavior on mixed or positive arrays.
Kadane's algorithm explained with complexity analysis covers the proof and edge cases in full.
The Prefix Sum Map Has Two Bugs, Not One
Two separate ways to get Subarray Sum Equals K wrong. Almost impressive.
The first is well-known: forgetting to seed the map with {0: 1}.
prefix_count = {} # BUG: missing base case prefix = 0 result = 0 for num in nums: prefix += num result += prefix_count.get(prefix - k, 0) prefix_count[prefix] = prefix_count.get(prefix, 0) + 1
If prefix == k at index i, the answer includes the subarray nums[0..i]. But looking up prefix - k == 0 in an empty map finds nothing. {0: 1} represents the empty prefix: before any elements, the sum is zero, and that has happened exactly once.
The second bug sneaks in even after you add the base case. The lookup must happen before the map update, not after.
prefix_count = {0: 1} prefix = 0 result = 0 for num in nums: prefix += num result += prefix_count.get(prefix - k, 0) # Check FIRST prefix_count[prefix] = prefix_count.get(prefix, 0) + 1 # Update AFTER
If you reverse the order, updating before looking up, you'll sometimes find prefix - k == 0 pointing to a prefix you just inserted this iteration. That counts a zero-length subarray ending at the current index, which isn't valid. Check before update. Always.
For the full pattern, prefix sums explained with range query examples is worth reading before your next interview.
Two Pointers Silently Assumes Sorted Input
The two-pointer technique works because the array is sorted. Move the left pointer right and the sum increases. Move the right pointer left and it decreases. This logic falls apart on an unsorted array. Nothing in the code signals that it fell apart.
Applying two pointers to an unsorted array produces wrong answers with no error. It just lies to you.
The fix depends on whether you can afford to lose index information. For Two Sum II (sorted input guaranteed), two pointers are fine. For vanilla Two Sum (unsorted, needs original indices), sorting first destroys the indices you're supposed to return. Use a hash map instead.
# Wrong for vanilla Two Sum: sort destroys original indices def two_sum_wrong(nums, target): nums.sort() # indices are now invalid left, right = 0, len(nums) - 1 while left < right: ... # Right for vanilla Two Sum def two_sum(nums, target): seen = {} for i, num in enumerate(nums): complement = target - num if complement in seen: return [seen[complement], i] seen[num] = i return []
Before applying two pointers to any array problem, ask explicitly: is this input sorted? If not, can you sort it without losing information you need? If either answer is no, use a hash map.
Two pointer algorithm: how one realization kills the nested loop covers when each variant applies.
Your Sliding Window Shrinks Too Late (or Too Early)
Variable-size sliding window problems follow a pattern: expand right, check a condition, shrink left. The shrink condition is where most bugs live.
A common one is using > when the problem requires >=. For minimum subarray length with sum at least target, the window should shrink whenever the sum meets the target, including exactly equal:
def min_subarray_len(target, nums): left = 0 current_sum = 0 min_len = float('inf') for right in range(len(nums)): current_sum += nums[right] while current_sum >= target: # NOT while current_sum > target min_len = min(min_len, right - left + 1) current_sum -= nums[left] left += 1 return min_len if min_len != float('inf') else 0
Using > target means windows with exactly the target sum never trigger the shrink, so they're never recorded as valid. The min_len never updates for those cases.
The second bug is forgetting to undo state when the left pointer moves. If you're tracking a character frequency map or a running product, you must remove nums[left] from the state before advancing left += 1. Skip that and the window condition describes the wrong window.
The mental model: the state variable must always accurately describe the current window, nothing outside it.
The sliding window technique from O(n²) to O(n) has worked examples of both fixed and variable size variants.
Python's in Operator Is O(n) on Lists
This one doesn't produce wrong answers. It produces Time Limit Exceeded submissions that look like working code.
# Looks O(n), actually O(n²) def contains_duplicate(nums): seen = [] for num in nums: if num in seen: # linear scan every time return True seen.append(num) return False
in on a Python list is a linear search. Running it inside a loop makes the function O(n²). On small inputs the difference is invisible, which is why this pattern survives until it hits a test case with 60,000 elements. Then you get a TLE and a very quiet ten seconds.
The same trap lives in list.pop(0): it looks like constant time but shifts every remaining element, costing O(n) per call.
# O(n) with set, O(1) per lookup def contains_duplicate(nums): seen = set() for num in nums: if num in seen: # hash lookup, O(1) return True seen.add(num) return False # For queue-style front removal, use deque from collections import deque q = deque() q.append(item) q.popleft() # O(1), not O(n)
Python hides a lot of linear-time work behind clean syntax. list.index(), list.remove(), list.insert(0, x), and x in list are all O(n). Knowing this is the difference between solutions that scale and solutions that quietly choke.
3Sum Needs Three Deduplication Guards, Not One
![When a developer finds a bug: let's hide. When a tester finds a bug: [alarm going off].](https://assets.spacecomplexity.ai/blog/content-images/array-bugs-coding-interview/1780752733327-meme-dev-vs-tester.jpg)
Three guards, and the one you skipped is the one the interviewer tests.
The sorted two-pointer approach to 3Sum is correct in its core logic. The deduplication is where candidates lose points.
After sorting, identical values are adjacent. If the outer loop visits two consecutive identical values, it generates the same triplet twice. If the inner pointers land on repeated values after finding a match, the same triplet appears again. The fix requires duplicate skipping at three separate points.
def three_sum(nums): nums.sort() result = [] for i in range(len(nums) - 2): if i > 0 and nums[i] == nums[i - 1]: # Guard 1: outer loop continue left, right = i + 1, len(nums) - 1 while left < right: total = nums[i] + nums[left] + nums[right] if total == 0: result.append([nums[i], nums[left], nums[right]]) while left < right and nums[left] == nums[left + 1]: # Guard 2 left += 1 while left < right and nums[right] == nums[right - 1]: # Guard 3 right -= 1 left += 1 right -= 1 elif total < 0: left += 1 else: right -= 1 return result
Note the i > 0 guard on the outer loop. Without it, nums[i] == nums[i-1] runs at i=0, comparing against index -1, which in Python wraps to the last element. That silently drops valid triplets.
Every level of the search needs its own deduplication. Missing any one of the three guards produces duplicates that are genuinely hard to spot by reading the code.
Array Bug Checklist: Before You Write a Single Line
Run through this before touching the keyboard on any array problem:
- Empty input: does
[]crash anything? - Single element:
[x]exposes index arithmetic mistakes. - All same values:
[1, 1, 1]tests duplicate handling. - All negative:
[-3, -2, -1]catches zero-initialization. - Sorted vs unsorted: does your approach depend on order?
- Modify in place or return new: are you allowed to mutate the input?
These are exactly the inputs an interviewer will reach for when your solution looks a little too confident. Practicing in a voice interview format where someone asks follow-up questions about edge cases is one of the most effective ways to internalize this checklist. SpaceComplexity runs mock interviews that probe these scenarios the way actual interviewers do. If you've been solving problems silently on LeetCode, it's worth trying the format at least once.
The Short Version
- Kadane's: initialize to
nums[0], reset tomax(current + num, num), never to0. - Prefix sum: always seed with
{0: 1}, always check before you insert. - Two pointers: confirm sorted input or sort first. If index info is required, use a hash map.
- Sliding window: use
>=for inclusive thresholds. Undo state when shrinking the left boundary. - Python
in: O(n) on lists. Usesetfor membership,dequefor front removal. - 3Sum: deduplicate at the outer loop, and both inner pointer moves after a match.
Further Reading
- Maximum subarray problem on Wikipedia
- Two Pointers Technique on GeeksforGeeks
- Subarrays vs Subsequences on GeeksforGeeks
- Prefix Sum array on GeeksforGeeks
- Integer overflow on Wikipedia