Understand the recursive state, choices, base case, and how the same recurrence becomes Kadane's Algorithm.
Given an array of integers nums, find the subarray with the largest sum and
return the sum.
A subarray is a contiguous non-empty sequence of elements within an array.
nums = [2,-3,4,-2,2,1,-1,4]8[4,-2,2,1,-1,4] has the largest sum, which is 8.
nums = [-1]-1
Constraints
Define:
This definition is powerful because if the subarray must end at index i, then
nums[i] must be included.
At index i, there are only two meaningful possibilities:
If the previous sum is harmful, start fresh. If it helps, extend it.
Use the example [2, -3, 4, -2, 2, 1, -1, 4]. Click “Next step” to see the recurrence evaluate each index.
Start a new subarray using only nums[i].
Continue the best subarray that ended at i - 1.
The only non-empty subarray that ends at index 0 is:
So solve(0) = nums[0].
Suppose i = 4 and nums[4] = 2.
solve(3) does not mean the answer for the whole array. It only means the best subarray
sum that ends exactly at index 3.
class Solution:
def maxSubArray(self, nums):
n = len(nums)
def solve(i):
# Maximum subarray sum that must end at index i
if i == 0:
return nums[0]
start_new = nums[i]
extend_previous = nums[i] + solve(i - 1)
return max(start_new, extend_previous)
answer = float('-inf')
for i in range(n):
answer = max(answer, solve(i))
return answer
The maximum subarray may end at any index, so the final answer is:
class Solution:
def maxSubArray(self, nums):
memo = {}
def solve(i):
if i == 0:
return nums[0]
if i in memo:
return memo[i]
memo[i] = max(
nums[i],
nums[i] + solve(i - 1)
)
return memo[i]
answer = float('-inf')
for i in range(len(nums)):
answer = max(answer, solve(i))
return answer
In the memoized version, solve(i) uses only solve(i - 1). Compute the
states in order, starting with solve(0) = nums[0]. Then a single variable can hold
the previous state instead of a memo dictionary.
Keep answer as well: current is the best sum ending at this index, while
answer is the best sum across all indices. This iterative form is Kadane's Algorithm.
The choices are the same as in solve(i): start at i or extend the best
subarray ending at i - 1. Iteration also avoids Python's recursion depth limit
for large inputs.
class Solution:
def maxSubArray(self, nums):
current = nums[0]
answer = nums[0]
for i in range(1, len(nums)):
previous_current = current # solve(i - 1)
start_new = nums[i]
extend_previous = nums[i] + previous_current
current = max(start_new, extend_previous) # solve(i)
answer = max(answer, current)
return answer