Python Program to Find Maximum Subarray Sum
max_ending_here = max(num, max_ending_here + num) and max_so_far = max(max_so_far, max_ending_here) to find the maximum subarray sum efficiently.Examples
How to Think About It
Algorithm
Code
def max_subarray_sum(nums): max_so_far = max_ending_here = nums[0] for num in nums[1:]: max_ending_here = max(num, max_ending_here + num) max_so_far = max(max_so_far, max_ending_here) return max_so_far print(max_subarray_sum([-2, 1, -3, 4, -1, 2, 1, -5, 4]))
Dry Run
Let's trace the example [-2, 1, -3, 4, -1, 2, 1, -5, 4] through the code
Initialize
max_so_far = -2, max_ending_here = -2
Process 1
max_ending_here = max(1, -2 + 1) = 1; max_so_far = max(-2, 1) = 1
Process -3
max_ending_here = max(-3, 1 + -3) = -2; max_so_far = max(1, -2) = 1
Process 4
max_ending_here = max(4, -2 + 4) = 4; max_so_far = max(1, 4) = 4
Process -1
max_ending_here = max(-1, 4 + -1) = 3; max_so_far = max(4, 3) = 4
Process 2
max_ending_here = max(2, 3 + 2) = 5; max_so_far = max(4, 5) = 5
Process 1
max_ending_here = max(1, 5 + 1) = 6; max_so_far = max(5, 6) = 6
Process -5
max_ending_here = max(-5, 6 + -5) = 1; max_so_far = max(6, 1) = 6
Process 4
max_ending_here = max(4, 1 + 4) = 5; max_so_far = max(6, 5) = 6
| max_ending_here | max_so_far |
|---|---|
| -2 | -2 |
| 1 | 1 |
| -2 | 1 |
| 4 | 4 |
| 3 | 4 |
| 5 | 5 |
| 6 | 6 |
| 1 | 6 |
| 5 | 6 |
Why This Works
Step 1: Track current subarray sum
The variable max_ending_here keeps the sum of the current subarray we are considering, resetting when it becomes less than the current number.
Step 2: Update maximum found
The variable max_so_far stores the highest sum found so far, updated whenever max_ending_here exceeds it.
Step 3: Efficient single pass
This approach only needs one pass through the list, making it efficient and simple without checking all subarrays.
Alternative Approaches
def max_subarray_sum_brute(nums): max_sum = nums[0] for i in range(len(nums)): current_sum = 0 for j in range(i, len(nums)): current_sum += nums[j] max_sum = max(max_sum, current_sum) return max_sum print(max_subarray_sum_brute([-2, 1, -3, 4, -1, 2, 1, -5, 4]))
def max_crossing_sum(nums, left, mid, right): left_sum = float('-inf') total = 0 for i in range(mid, left - 1, -1): total += nums[i] if total > left_sum: left_sum = total right_sum = float('-inf') total = 0 for i in range(mid + 1, right + 1): total += nums[i] if total > right_sum: right_sum = total return left_sum + right_sum def max_subarray_sum_divide(nums, left, right): if left == right: return nums[left] mid = (left + right) // 2 left_max = max_subarray_sum_divide(nums, left, mid) right_max = max_subarray_sum_divide(nums, mid + 1, right) cross_max = max_crossing_sum(nums, left, mid, right) return max(left_max, right_max, cross_max) print(max_subarray_sum_divide([-2, 1, -3, 4, -1, 2, 1, -5, 4], 0, 8))
Complexity: O(n) time, O(1) space
Time Complexity
Kadane's algorithm scans the list once, updating sums in constant time per element, so it runs in linear time O(n).
Space Complexity
It uses only a few variables to track sums, so it requires constant extra space O(1).
Which Approach is Fastest?
Kadane's algorithm is fastest and simplest for this problem compared to brute force (O(n^2)) and divide and conquer (O(n log n)).
| Approach | Time | Space | Best For |
|---|---|---|---|
| Kadane's Algorithm | O(n) | O(1) | Large arrays, efficient |
| Brute Force | O(n^2) | O(1) | Small arrays, simple code |
| Divide and Conquer | O(n log n) | O(log n) | When recursion is preferred |