The largest-sum subarray
Given a list of integers nums, return the largest sum of a non-empty contiguous subarray.
Examples
| Input | Output | Why |
|---|---|---|
nums = [-2,1,-3,4,-1,2,1,-5,4] | 6 | The subarray 4, −1, 2, 1. |
nums = [5,4,-1,7,8] | 23 | The whole list. |
nums = [-3,-1,-2] | -1 | All negative: the best single element. |
Constraints
- 1 ≤ nums.length ≤ 10⁵
- −10⁴ ≤ nums[i] ≤ 10⁴
Hints
Hint 1
Let end[i] be the best sum of a subarray ending exactly at i.
Hint 2
end[i] = max(end[i − 1] + nums[i], nums[i]): extend or restart.
Hint 3
The answer is the largest end[i]. Start from nums[0], not 0, so an all-negative list works.
Where people lose marks
- Initialising the best to 0, which returns 0 for an all-negative list.
- Resetting to 0 instead of to the current element.
Dry run on [-2,1,-3,4,-1,2,1,-5,4]
Read it one frame at a time, the way you would trace the code on paper in an interview. Each frame shows the state after the step it describes.
-
Step 1 / 9nums-2011-3243-142516-5748end-20·1·2·3·4·5·6·7·8
Base case: end[0] = -2.
-
Step 2 / 9nums-2011-3243-142516-5748end-2011·2·3·4·5·6·7·8
Restart at 1 (extending gives only -1).
-
Step 3 / 9nums-2011-3243-142516-5748end-2011-22·3·4·5·6·7·8
Extend: 1 + -3 = -2.
-
Step 4 / 9nums-2011-3243-142516-5748end-2011-2243·4·5·6·7·8
Restart at 4 (extending gives only 2).
-
Step 5 / 9nums-2011-3243-142516-5748end-2011-224334·5·6·7·8
Extend: 4 + -1 = 3.
-
Step 6 / 9nums-2011-3243-142516-5748end-2011-22433455·6·7·8
Extend: 3 + 2 = 5.
-
Step 7 / 9nums-2011-3243-142516-5748end-2011-2243345566·7·8
Extend: 5 + 1 = 6.
-
Step 8 / 9nums-2011-3243-142516-5748end-2011-224334556617·8
Extend: 6 + -5 = 1.
-
Step 9 / 9nums-2011-3243-142516-5748end-2011-22433455661758
Extend: 1 + 4 = 5. The answer is the largest entry, 6.
How to think about it
Kadane's algorithm. The best subarray ending at i either extends the best one ending at i − 1 or starts fresh at i,
so end = max(end + x, x). Track the largest value end takes. Initialising with the first element
rather than 0 keeps the subarray non-empty, which matters when every number is negative.
Complexity. Time O(n) · Space O(1)
The solution, in six languages
Each one is compiled and run against the test table before it is published. Java is reviewed by hand.
def max_subarray(nums):
best = end = nums[0] # end: best sum of a subarray ending here
for x in nums[1:]:
end = max(end + x, x) # extend, or restart at x
best = max(best, end)
return best#include <algorithm>
#include <vector>
long long solve(const std::vector<int>& nums) {
long long best = nums[0], end = nums[0];
for (size_t i = 1; i < nums.size(); ++i) {
end = std::max(end + nums[i], (long long)nums[i]); // extend or restart
best = std::max(best, end);
}
return best;
}class Solution {
public long maxSubarray(int[] nums) {
long best = nums[0], end = nums[0];
for (int i = 1; i < nums.length; i++) {
end = Math.max(end + nums[i], nums[i]); // extend or restart
best = Math.max(best, end);
}
return best;
}
}function maxSubarray(nums) {
let best = nums[0], end = nums[0];
for (let i = 1; i < nums.length; i++) {
end = Math.max(end + nums[i], nums[i]); // extend or restart
best = Math.max(best, end);
}
return best;
}fn solve(nums: &[i64]) -> i64 {
let (mut best, mut end) = (nums[0], nums[0]);
for &x in &nums[1..] {
end = (end + x).max(x); // extend or restart
best = best.max(end);
}
best
}solve :: [Int] -> Int
solve (x : xs) = fst (foldl step (x, x) xs)
where
-- (best so far, best ending here)
step (best, end) y = let end' = max (end + y) y in (max best end', end')
solve [] = 0
Variants to try
- Return the start and end of the best subarray.
- At most k elements long: a monotonic deque over prefix sums.
- Divide and conquer in O(n log n).
Next problems
One trade: the best profit
Buy on one day and sell on a later day. The best profit from selling today is today's price minus the lowest price so far.
Open the problem → Medium20 minThe largest product of a subarray
Return the largest product of a non-empty contiguous subarray. A negative number swaps the best and the worst, so keep both.
Open the problem → Medium20 minThe largest sum on a circle
The list wraps around. The best stretch either does not wrap (ordinary Kadane) or does, and then it is the total minus the worst stretch.
Open the problem →Write a solution and run it against the real test table.
Keep going
One trade: the best profit
Buy on one day and sell on a later day. The best profit from selling today is today's price minus the lowest price so far.
Open the problem → Medium20 minThe largest product of a subarray
Return the largest product of a non-empty contiguous subarray. A negative number swaps the best and the worst, so keep both.
Open the problem → Medium20 minThe largest sum on a circle
The list wraps around. The best stretch either does not wrap (ordinary Kadane) or does, and then it is the total minus the worst stretch.
Open the problem → Dynamic programmingThe pattern behind it
Write the recursion, notice the repeats, fill a table in an order that makes each entry final.
Read the pattern →Preparing for a real process? Quant interview preparation, or book a free 20-minute call.