Given an integer array nums
, find the subarray with the largest sum, and return its sum.
For example:
nums = [-2,1,-3,4,-1,2,1,-5,4]
should return 6
because the subarray [4,-1,2,1]
has the largest sum of 6.nums = [1]
should return 1
because the subarray [1]
has the largest sum of 1.nums = [5,4,-1,7,8]
should return 23
because the subarray [5,4,-1,7,8]
has the largest sum of 23.Explain your approach and the time and space complexity of your solution. Also, consider edge cases such as an array with all negative numbers or an empty array. Can you describe a divide and conquer approach as well?
A naive approach would be to iterate through all possible subarrays, calculate their sums, and keep track of the maximum sum encountered. This involves two nested loops:
Code Example (Python):
def max_subarray_brute_force(nums):
max_sum = float('-inf')
for i in range(len(nums)):
for j in range(i, len(nums)):
current_sum = sum(nums[i:j+1])
max_sum = max(max_sum, current_sum)
return max_sum
Time Complexity: O(n^2) due to the nested loops. The sum()
function inside the inner loop also takes O(n) in the worst case, making it technically O(n^3). However, the dominant factor is still O(n^2) because the sum can be calculated incrementally.
Space Complexity: O(1) as it uses only a constant amount of extra space.
Kadane's Algorithm provides an efficient way to solve this problem in linear time. The idea is to maintain two variables:
max_so_far
: Stores the maximum sum found so far.current_max
: Stores the maximum sum ending at the current position.For each element in the array, we update current_max
by either starting a new subarray from the current element or extending the previous subarray by adding the current element. We then update max_so_far
with the maximum of max_so_far
and current_max
.
Code Example (Python):
def max_subarray_kadane(nums):
max_so_far = float('-inf')
current_max = 0
for i in range(len(nums)):
current_max = max(nums[i], current_max + nums[i])
max_so_far = max(max_so_far, current_max)
return max_so_far
Time Complexity: O(n) as it iterates through the array only once.
Space Complexity: O(1) as it uses only a constant amount of extra space.
1 <= nums.length <= 10^5
, it's good to consider what should happen with an empty array. You might throw an exception or return 0. The provided code will actually still work because it would not execute the loop, and the initial value of max_so_far
(negative infinity) will be returned, which is not ideal. It would be better to check for len(nums) == 0
and return 0 or throw an exception.max_so_far
is initialized to negative infinity, and it will find the least negative number (i.e., the largest number) in the array.While Kadane's algorithm is generally preferred for its simplicity and efficiency, the divide and conquer approach offers an alternative perspective.
The maximum subarray sum crossing the midpoint can be found by:
The final result is the maximum of the three sums (left half, right half, crossing the midpoint).
Time Complexity: O(n log n)
Space Complexity: O(log n) due to the recursive calls.