You should aim for a solution with O(n) time and O(1) space, where n is the size of the input array.
Hint 1
A brute force approach would be to compute the sum of every subarray and return the maximum among them. This would be an O(n^2) approach. Can you think of a better way? Maybe you should consider a dynamic programming-based approach.
Hint 2
Instead of calculating the sum for every subarray, try maintaining a running sum. Maybe you should consider whether extending the previous sum or starting fresh with the current element gives a better result. Can you think of a way to track this efficiently?
Hint 3
We use a variable curSum to track the sum of the elements. At each index, we have two choices: either add the current element to curSum or start a new subarray by resetting curSum to the current element. Maybe you should track the maximum sum at each step and update the global maximum accordingly.
Before attempting this problem, you should be comfortable with:
Kadane's Algorithm - The classic O(n) solution for maximum subarray problems using dynamic programming
Dynamic Programming - Understanding how to build solutions from subproblems (top-down and bottom-up approaches)
Divide and Conquer - Alternative approach that splits the array and handles cross-boundary subarrays
Recursion with Memoization - Converting recursive solutions to efficient DP solutions
1. Brute Force
Intuition
This problem asks us to find the maximum sum of any contiguous subarray.
The most straightforward way to think about this is:
try every possible subarray
calculate its sum
keep track of the maximum sum we see
A subarray is defined by a start index i and an end index j. By fixing i and expanding j to the right, we can compute the sum of all subarrays that start at i.
This approach is easy to understand and works well for learning, but it is not efficient for large inputs.
Algorithm
Let n be the length of the array.
Initialize the result res with the first element of the array.
Iterate over all possible starting indices i from 0 to n - 1:
classSolution:defmaxSubArray(self, nums: List[int])->int:
n, res =len(nums), nums[0]for i inrange(n):
cur =0for j inrange(i, n):
cur += nums[j]
res =max(res, cur)return res
publicclassSolution{publicintmaxSubArray(int[] nums){int n = nums.length, res = nums[0];for(int i =0; i < n; i++){int cur =0;for(int j = i; j < n; j++){
cur += nums[j];
res =Math.max(res, cur);}}return res;}}
classSolution{public:intmaxSubArray(vector<int>& nums){int n = nums.size(), res = nums[0];for(int i =0; i < n; i++){int cur =0;for(int j = i; j < n; j++){
cur += nums[j];
res =max(res, cur);}}return res;}};
classSolution{/**
* @param {number[]} nums
* @return {number}
*/maxSubArray(nums){let n = nums.length,
res = nums[0];for(let i =0; i < n; i++){let cur =0;for(let j = i; j < n; j++){
cur += nums[j];
res = Math.max(res, cur);}}return res;}}
publicclassSolution{publicintMaxSubArray(int[] nums){int n = nums.Length, res = nums[0];for(int i =0; i < n; i++){int cur =0;for(int j = i; j < n; j++){
cur += nums[j];
res = Math.Max(res, cur);}}return res;}}
funcmaxSubArray(nums []int)int{
n :=len(nums)
res := nums[0]for i :=0; i < n; i++{
cur :=0for j := i; j < n; j++{
cur += nums[j]if cur > res {
res = cur
}}}return res
}
class Solution {funmaxSubArray(nums: IntArray): Int {val n = nums.size
var res = nums[0]for(i in0 until n){var cur =0for(j in i until n){
cur += nums[j]
res =maxOf(res, cur)}}return res
}}
classSolution{funcmaxSubArray(_ nums:[Int])->Int{let n = nums.count
var res = nums[0]for i in0..<n {var cur =0for j in i..<n {
cur += nums[j]
res =max(res, cur)}}return res
}}
Time & Space Complexity
Time complexity: O(n2)
Space complexity: O(1)
2. Recursion
Intuition
We want the maximum sum of a contiguous subarray.
Using recursion, we can think of the problem as making a decision at each index:
either we haven’t started a subarray yet
or we are already inside a subarray and can choose whether to continue it or stop
The recursive function keeps track of this using a flag:
flag = False - we have not started a subarray yet
flag = True - we are currently building a subarray
The function answers the question: “What is the maximum subarray sum we can get starting from index i, given whether we are already inside a subarray or not?”
By exploring both possibilities at every step, the recursion eventually finds the best contiguous subarray.
Algorithm
Define a recursive function dfs(i, flag):
i is the current index in the array
flag indicates whether a subarray has already started
Base case:
If i reaches the end of the array:
Return 0 if a subarray was already started
Otherwise return a very small value (to ensure at least one element is chosen)
If flag is True (we are inside a subarray):
We have two choices:
stop the subarray - return 0
continue the subarray - add nums[i] and recurse
Take the maximum of these two options
If flag is False (we have not started yet):
We can either:
skip the current element and stay outside the subarray
classSolution:defmaxSubArray(self, nums: List[int])->int:defdfs(i, flag):if i ==len(nums):return0if flag else-1e6if flag:returnmax(0, nums[i]+ dfs(i +1,True))returnmax(dfs(i +1,False), nums[i]+ dfs(i +1,True))return dfs(0,False)
publicclassSolution{publicintmaxSubArray(int[] nums){returndfs(nums,0,false);}privateintdfs(int[] nums,int i,boolean flag){if(i == nums.length){return flag ?0:(int)-1e6;}if(flag){returnMath.max(0, nums[i]+dfs(nums, i +1,true));}returnMath.max(dfs(nums, i +1,false),
nums[i]+dfs(nums, i +1,true));}}
classSolution{public:intmaxSubArray(vector<int>& nums){returndfs(nums,0,false);}private:intdfs(vector<int>& nums,int i,bool flag){if(i == nums.size())return flag ?0:-1e6;if(flag)returnmax(0, nums[i]+dfs(nums, i +1,true));returnmax(dfs(nums, i +1,false),
nums[i]+dfs(nums, i +1,true));}};
publicclassSolution{publicintMaxSubArray(int[] nums){returnDfs(nums,0,false);}privateintDfs(int[] nums,int i,bool flag){if(i == nums.Length)return flag ?0:(int)-1e6;if(flag)return Math.Max(0, nums[i]+Dfs(nums, i +1,true));return Math.Max(Dfs(nums, i +1,false),
nums[i]+Dfs(nums, i +1,true));}}
funcmaxSubArray(nums []int)int{var dfs func(i int, flag bool)int
dfs =func(i int, flag bool)int{if i ==len(nums){if flag {return0}return-1e6}if flag {returnmax(0, nums[i]+dfs(i +1,true))}returnmax(dfs(i +1,false), nums[i]+dfs(i +1,true))}returndfs(0,false)}funcmax(a, b int)int{if a > b {return a
}return b
}
class Solution {funmaxSubArray(nums: IntArray): Int {fundfs(i: Int, flag: Boolean): Int {if(i == nums.size){returnif(flag)0else Int.MIN_VALUE
}returnif(flag){maxOf(0, nums[i]+dfs(i +1,true))}else{maxOf(dfs(i +1,false), nums[i]+dfs(i +1,true))}}returndfs(0,false)}}
classSolution{funcmaxSubArray(_ nums:[Int])->Int{funcdfs(_ i:Int,_ flag:Bool)->Int{if i == nums.count {return flag ?0:Int.min
}if flag {returnmax(0, nums[i]+dfs(i +1,true))}returnmax(dfs(i +1,false), nums[i]+dfs(i +1,true))}returndfs(0,false)}}
Time & Space Complexity
Time complexity: O(2n)
Space complexity: O(n)
3. Dynamic Programming (Top-Down)
Intuition
We want to find the maximum sum of a contiguous subarray.
In the recursive solution, we modeled the problem using two states:
we have not started a subarray yet
we are already inside a subarray
However, plain recursion repeats the same computations many times. To optimize this, we use top-down dynamic programming (memoization).
Each state is uniquely identified by:
i: the current index in the array
flag: whether a subarray has already started (True) or not (False).
The function answers: “What is the maximum subarray sum we can get starting from index i, given whether a subarray is already in progress?”
By storing results for each (i, flag) state, we avoid recomputing them.
Algorithm
Create a memo table memo where:
memo[i][flag] stores the maximum subarray sum starting at index i given whether a subarray has started.
Define a recursive function dfs(i, flag):
i is the current index
flag indicates whether a subarray is already in progress.
Base case:
If i reaches the end of the array:
Return 0 if a subarray was started
Otherwise return a very small value (to force choosing at least one element).
If the result for (i, flag) is already stored in memo:
publicclassSolution{privateint[][] memo;publicintmaxSubArray(int[] nums){
memo =newint[nums.length +1][2];for(int[] row : memo)Arrays.fill(row,Integer.MIN_VALUE);returndfs(nums,0,false);}privateintdfs(int[] nums,int i,boolean flag){if(i == nums.length)return flag ?0:(int)-1e6;int f = flag ?1:0;if(memo[i][f]!=Integer.MIN_VALUE)return memo[i][f];
memo[i][f]= flag ?Math.max(0, nums[i]+dfs(nums, i +1,true)):Math.max(dfs(nums, i +1,false),
nums[i]+dfs(nums, i +1,true));return memo[i][f];}}
classSolution{public:intmaxSubArray(vector<int>& nums){
vector<vector<int>>memo(nums.size()+1,vector<int>(2, INT_MIN));returndfs(nums,0,false, memo);}private:intdfs(vector<int>& nums,int i,bool flag, vector<vector<int>>& memo){if(i == nums.size())return flag ?0:-1e6;int f = flag ?1:0;if(memo[i][f]!= INT_MIN)return memo[i][f];if(flag)
memo[i][f]=max(0, nums[i]+dfs(nums, i +1,true, memo));else
memo[i][f]=max(dfs(nums, i +1,false, memo),
nums[i]+dfs(nums, i +1,true, memo));return memo[i][f];}};
publicclassSolution{privateint[,] memo;publicintMaxSubArray(int[] nums){
memo =newint[nums.Length +1,2];for(int i =0; i <= nums.Length; i++){
memo[i,0]= memo[i,1]=int.MinValue;}returnDfs(nums,0,false);}privateintDfs(int[] nums,int i,bool flag){if(i == nums.Length)return flag ?0:-1000000;int f = flag ?1:0;if(memo[i, f]!=int.MinValue)return memo[i, f];
memo[i, f]=flag ? Math.Max(0, nums[i]+Dfs(nums, i +1,true)): Math.Max(Dfs(nums, i +1,false),
nums[i]+Dfs(nums, i +1,true));return memo[i, f];}}
funcmaxSubArray(nums []int)int{
memo :=make([][2]*int,len(nums)+1)for i :=range memo {
memo[i]=[2]*int{nil,nil}}var dfs func(int,int)int
dfs =func(i, flag int)int{if i ==len(nums){if flag ==1{return0}return-1000000}if memo[i][flag]!=nil{return*memo[i][flag]}if flag ==1{
result :=max(0, nums[i]+dfs(i+1,1))
memo[i][flag]=&result
}else{
result :=max(dfs(i+1,0), nums[i]+dfs(i+1,1))
memo[i][flag]=&result
}return*memo[i][flag]}returndfs(0,0)}funcmax(a, b int)int{if a > b {return a
}return b
}
class Solution {funmaxSubArray(nums: IntArray): Int {val memo =Array(nums.size +1){ arrayOfNulls<Int>(2)}fundfs(i: Int, flag: Int): Int {if(i == nums.size){returnif(flag ==1)0else-1000000}if(memo[i][flag]!=null){return memo[i][flag]!!}
memo[i][flag]=if(flag ==1){maxOf(0, nums[i]+dfs(i +1,1))}else{maxOf(dfs(i +1,0), nums[i]+dfs(i +1,1))}return memo[i][flag]!!}returndfs(0,0)}}
classSolution{funcmaxSubArray(_ nums:[Int])->Int{var memo =Array(repeating:[Int?](repeating:nil, count:2), count: nums.count +1)funcdfs(_ i:Int,_ flag:Bool)->Int{if i == nums.count {return flag ?0:Int.min
}iflet value = memo[i][flag ?1:0]{return value
}if flag {
memo[i][flag ?1:0]=max(0, nums[i]+dfs(i +1,true))}else{
memo[i][flag ?1:0]=max(dfs(i +1,false), nums[i]+dfs(i +1,true))}return memo[i][flag ?1:0]!}returndfs(0,false)}}
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(n)
4. Dynamic Programming (Bottom-Up)
Intuition
We want the maximum sum of a contiguous subarray.
From the recursive and top-down DP solutions, we observed two useful states:
the best subarray sum starting exactly at index i
the best subarray sum starting at or after index i
Instead of recursion, we can compute these values iteratively using bottom-up dynamic programming.
At each index, we decide:
whether to start a new subarray at the current element
or extend a subarray from the next index
By filling the DP table from right to left, all needed future values are already known.
Algorithm
Let n be the length of the array.
Create a DP table dp of size n x 2:
dp[i][1] = maximum subarray sum that must start at index i
dp[i][0] = maximum subarray sum that starts at index i or later
Initialize the base case at the last index:
dp[n - 1][1] = nums[n - 1]
dp[n - 1][0] = nums[n - 1]
Iterate i from n - 2 down to 0:
Compute dp[i][1]:
either start a new subarray at i - nums[i]
or extend the subarray from i + 1 - nums[i] + dp[i + 1][1]
Compute dp[i][0]:
either the best subarray starts later - dp[i + 1][0]
or it starts exactly at i - dp[i][1]
After filling the table, dp[0][0] contains the maximum subarray sum.
publicclassSolution{publicintmaxSubArray(int[] nums){int n = nums.length;int[][] dp =newint[n +1][2];
dp[n -1][1]= dp[n -1][0]= nums[n -1];for(int i = n -2; i >=0; i--){
dp[i][1]=Math.max(nums[i], nums[i]+ dp[i +1][1]);
dp[i][0]=Math.max(dp[i +1][0], dp[i][1]);}return dp[0][0];}}
classSolution{public:intmaxSubArray(vector<int>& nums){int n = nums.size();
vector<vector<int>>dp(n +1,vector<int>(2,0));
dp[n -1][1]= dp[n -1][0]= nums[n -1];for(int i = n -2; i >=0; i--){
dp[i][1]=max(nums[i], nums[i]+ dp[i +1][1]);
dp[i][0]=max(dp[i +1][0], dp[i][1]);}return dp[0][0];}};
classSolution{/**
* @param {number[]} nums
* @return {number}
*/maxSubArray(nums){const n = nums.length;const dp = Array.from({length: n +1},()=>Array(2).fill(0));
dp[n -1][1]= dp[n -1][0]= nums[n -1];for(let i = n -2; i >=0; i--){
dp[i][1]= Math.max(nums[i], nums[i]+ dp[i +1][1]);
dp[i][0]= Math.max(dp[i +1][0], dp[i][1]);}return dp[0][0];}}
publicclassSolution{publicintMaxSubArray(int[] nums){int n = nums.Length;int[,] dp =newint[n +1,2];
dp[n -1,1]= dp[n -1,0]= nums[n -1];for(int i = n -2; i >=0; i--){
dp[i,1]= Math.Max(nums[i], nums[i]+ dp[i +1,1]);
dp[i,0]= Math.Max(dp[i +1,0], dp[i,1]);}return dp[0,0];}}
funcmaxSubArray(nums []int)int{
n :=len(nums)
dp :=make([][]int, n)for i :=range dp {
dp[i]=make([]int,2)}
dp[n-1][1]= nums[n-1]
dp[n-1][0]= nums[n-1]for i := n-2; i >=0; i--{
dp[i][1]=max(nums[i], nums[i]+ dp[i+1][1])
dp[i][0]=max(dp[i+1][0], dp[i][1])}return dp[0][0]}funcmax(a, b int)int{if a > b {return a
}return b
}
class Solution {funmaxSubArray(nums: IntArray): Int {val n = nums.size
val dp =Array(n){IntArray(2)}
dp[n-1][1]= nums[n-1]
dp[n-1][0]= nums[n-1]for(i in n-2 downTo 0){
dp[i][1]=maxOf(nums[i], nums[i]+ dp[i+1][1])
dp[i][0]=maxOf(dp[i+1][0], dp[i][1])}return dp[0][0]}}
classSolution{funcmaxSubArray(_ nums:[Int])->Int{let n = nums.count
var dp =Array(repeating:[0,0], count: n)
dp[n -1][1]= nums[n -1]
dp[n -1][0]= nums[n -1]for i in(0..<n-1).reversed(){
dp[i][1]=max(nums[i], nums[i]+ dp[i +1][1])
dp[i][0]=max(dp[i +1][0], dp[i][1])}return dp[0][0]}}
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(n)
5. Dynamic Programming (Space Optimized)
Intuition
We want the maximum sum of a contiguous subarray.
At every position, we have a simple choice:
start a new subarray at the current element
or extend the subarray that ended at the previous index
If the sum up to the previous index is negative, extending it would only make things worse, so we start fresh at the current element.
This idea allows us to keep track of the best subarray sum ending at each index and update it in a single pass.
Algorithm
Create an array dp where:
dp[i] represents the maximum subarray sum ending at index i.
Initialize dp as a copy of nums since the smallest subarray ending at each index is the element itself.
Iterate through the array from index 1 to the end:
Update dp[i] as:
the maximum of starting fresh at nums[i]
or extending the previous subarray: nums[i] + dp[i - 1].
The maximum subarray sum is the maximum value in dp.
publicclassSolution{publicintMaxSubArray(int[] nums){int[] dp =(int[])nums.Clone();for(int i =1; i < nums.Length; i++){
dp[i]= Math.Max(nums[i], nums[i]+ dp[i -1]);}int maxSum = dp[0];foreach(int sum in dp){
maxSum = Math.Max(maxSum, sum);}return maxSum;}}
funcmaxSubArray(nums []int)int{
dp :=make([]int,len(nums))copy(dp, nums)for i :=1; i <len(nums); i++{
dp[i]=max(nums[i], nums[i]+ dp[i-1])}
maxSum := dp[0]for_, v :=range dp {if v > maxSum {
maxSum = v
}}return maxSum
}funcmax(a, b int)int{if a > b {return a
}return b
}
class Solution {funmaxSubArray(nums: IntArray): Int {val dp = nums.copyOf()for(i in1 until nums.size){
dp[i]=maxOf(nums[i], nums[i]+ dp[i-1])}return dp.maxOrNull()?: nums[0]}}
classSolution{funcmaxSubArray(_ nums:[Int])->Int{var dp = nums
for i in1..<nums.count {
dp[i]=max(nums[i], nums[i]+ dp[i -1])}return dp.max()??0}}
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(n)
6. Kadane's Algorithm
Intuition
We want the maximum sum of a contiguous subarray.
Kadane’s Algorithm is based on one simple observation:
if the running sum becomes negative, keeping it will only reduce the sum of any future subarray
So whenever the current sum drops below zero, we reset it and start a new subarray from the next element.
As we scan the array once, we keep track of:
the best subarray sum ending at the current position
the best subarray sum seen overall
Algorithm
Initialize:
curSum = 0 to track the running subarray sum
maxSub as the first element (handles all-negative arrays).
Iterate through each number in the array:
If curSum becomes negative:
reset it to 0 (start a new subarray).
Add the current number to curSum.
Update maxSub with the maximum of maxSub and curSum.
classSolution:defmaxSubArray(self, nums: List[int])->int:
maxSub, curSum = nums[0],0for num in nums:if curSum <0:
curSum =0
curSum += num
maxSub =max(maxSub, curSum)return maxSub
publicclassSolution{publicintmaxSubArray(int[] nums){int maxSub = nums[0], curSum =0;for(int num : nums){if(curSum <0){
curSum =0;}
curSum += num;
maxSub =Math.max(maxSub, curSum);}return maxSub;}}
classSolution{public:intmaxSubArray(vector<int>& nums){int maxSub = nums[0], curSum =0;for(int num : nums){if(curSum <0){
curSum =0;}
curSum += num;
maxSub =max(maxSub, curSum);}return maxSub;}};
classSolution{/**
* @param {number[]} nums
* @return {number}
*/maxSubArray(nums){let maxSub = nums[0],
curSum =0;for(const num of nums){if(curSum <0){
curSum =0;}
curSum += num;
maxSub = Math.max(maxSub, curSum);}return maxSub;}}
publicclassSolution{publicintMaxSubArray(int[] nums){int maxSub = nums[0], curSum =0;foreach(int num in nums){if(curSum <0){
curSum =0;}
curSum += num;
maxSub = Math.Max(maxSub, curSum);}return maxSub;}}
funcmaxSubArray(nums []int)int{
maxSub, curSum := nums[0],0for_, num :=range nums {if curSum <0{
curSum =0}
curSum += num
maxSub =max(maxSub, curSum)}return maxSub
}funcmax(a, b int)int{if a > b {return a
}return b
}
class Solution {funmaxSubArray(nums: IntArray): Int {var maxSub = nums[0]var curSum =0for(num in nums){if(curSum <0){
curSum =0}
curSum += num
maxSub =maxOf(maxSub, curSum)}return maxSub
}}
classSolution{funcmaxSubArray(_ nums:[Int])->Int{var maxSub = nums[0]var curSum =0for num in nums {if curSum <0{
curSum =0}
curSum += num
maxSub =max(maxSub, curSum)}return maxSub
}}
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(1)
7. Divide & Conquer
Intuition
We want the maximum sum of a contiguous subarray.
Using divide and conquer, we split the array into two halves and solve the problem recursively. For any subarray [l .. r], the maximum subarray must be one of these three cases:
Entirely in the left half
Entirely in the right half
Crossing the middle (includes the middle element)
The first two cases are solved recursively. The third case is handled by:
taking the maximum sum extending left from the middle
taking the maximum sum extending right from the middle
adding both to the middle element
The recursive function represents: “What is the maximum subarray sum within the range [l .. r]?”
Algorithm
Define a recursive function dfs(l, r):
If l > r, return negative infinity (invalid range).
Find the middle index m of the range [l .. r].
Compute the maximum subarray sum that crosses the middle:
Move left from m - 1 to l, keeping the maximum prefix sum
Move right from m + 1 to r, keeping the maximum prefix sum
Combine them with nums[m].
Recursively compute:
maximum subarray in the left half - dfs(l, m - 1)
maximum subarray in the right half - dfs(m + 1, r).
Return the maximum of:
left result
right result
crossing-middle result.
Start the recursion with the full range [0 .. n - 1].
classSolution:defmaxSubArray(self, nums: List[int])->int:defdfs(l, r):if l > r:returnfloat("-inf")
m =(l + r)>>1
leftSum = rightSum = curSum =0for i inrange(m -1, l -1,-1):
curSum += nums[i]
leftSum =max(leftSum, curSum)
curSum =0for i inrange(m +1, r +1):
curSum += nums[i]
rightSum =max(rightSum, curSum)return(max(dfs(l, m -1),
dfs(m +1, r),
leftSum + nums[m]+ rightSum))return dfs(0,len(nums)-1)
publicclassSolution{publicintmaxSubArray(int[] nums){returndfs(nums,0, nums.length -1);}privateintdfs(int[] nums,int l,int r){if(l > r){returnInteger.MIN_VALUE;}int m =(l + r)>>1;int leftSum =0, rightSum =0, curSum =0;for(int i = m -1; i >= l; i--){
curSum += nums[i];
leftSum =Math.max(leftSum, curSum);}
curSum =0;for(int i = m +1; i <= r; i++){
curSum += nums[i];
rightSum =Math.max(rightSum, curSum);}returnMath.max(dfs(nums, l, m -1),Math.max(dfs(nums, m +1, r),
leftSum + nums[m]+ rightSum));}}
classSolution{public:intmaxSubArray(vector<int>& nums){returndfs(nums,0, nums.size()-1);}private:intdfs(vector<int>& nums,int l,int r){if(l > r){return INT_MIN;}int m =(l + r)>>1;int leftSum =0, rightSum =0, curSum =0;for(int i = m -1; i >= l;--i){
curSum += nums[i];
leftSum =max(leftSum, curSum);}
curSum =0;for(int i = m +1; i <= r;++i){
curSum += nums[i];
rightSum =max(rightSum, curSum);}returnmax(dfs(nums, l, m -1),max(dfs(nums, m +1, r),
leftSum + nums[m]+ rightSum));}};
classSolution{/**
* @param {number[]} nums
* @return {number}
*/maxSubArray(nums){constdfs=(l, r)=>{if(l > r){return-Infinity;}let m =(l + r)>>1;let leftSum =0,
rightSum =0,
curSum =0;for(let i = m -1; i >= l; i--){
curSum += nums[i];
leftSum = Math.max(leftSum, curSum);}
curSum =0;for(let i = m +1; i <= r; i++){
curSum += nums[i];
rightSum = Math.max(rightSum, curSum);}return Math.max(dfs(l, m -1),
Math.max(dfs(m +1, r), leftSum + nums[m]+ rightSum),);};returndfs(0, nums.length -1);}}
publicclassSolution{publicintMaxSubArray(int[] nums){returnDfs(nums,0, nums.Length -1);}privateintDfs(int[] nums,int l,int r){if(l > r){returnint.MinValue;}int m =(l + r)>>1;int leftSum =0, rightSum =0, curSum =0;for(int i = m -1; i >= l; i--){
curSum += nums[i];
leftSum = Math.Max(leftSum, curSum);}
curSum =0;for(int i = m +1; i <= r; i++){
curSum += nums[i];
rightSum = Math.Max(rightSum, curSum);}return Math.Max(Dfs(nums, l, m -1),
Math.Max(Dfs(nums, m +1, r),
leftSum + nums[m]+ rightSum));}}
funcmaxSubArray(nums []int)int{var dfs func(l, r int)int
dfs =func(l, r int)int{if l > r {return math.MinInt64
}
m :=(l + r)>>1
leftSum, rightSum, curSum :=0,0,0for i := m -1; i >= l; i--{
curSum += nums[i]if curSum > leftSum {
leftSum = curSum
}}
curSum =0for i := m +1; i <= r; i++{
curSum += nums[i]if curSum > rightSum {
rightSum = curSum
}}
maxLeft :=dfs(l, m-1)
maxRight :=dfs(m+1, r)
crossSum := leftSum + nums[m]+ rightSum
returnmax(max(maxLeft, maxRight), crossSum)}returndfs(0,len(nums)-1)}funcmax(a, b int)int{if a > b {return a
}return b
}
class Solution {funmaxSubArray(nums: IntArray): Int {fundfs(l: Int, r: Int): Int {if(l > r){return Int.MIN_VALUE
}val m =(l + r)shr1var leftSum =0var rightSum =0var curSum =0for(i in(m -1) downTo l){
curSum += nums[i]
leftSum =maxOf(leftSum, curSum)}
curSum =0for(i in(m +1)..r){
curSum += nums[i]
rightSum =maxOf(rightSum, curSum)}returnmaxOf(dfs(l, m -1),dfs(m +1, r),
leftSum + nums[m]+ rightSum
)}returndfs(0, nums.size -1)}}
classSolution{funcmaxSubArray(_ nums:[Int])->Int{funcdfs(_ l:Int,_ r:Int)->Int{if l > r {returnInt.min
}let m =(l + r)/2var leftSum =0var rightSum =0var curSum =0for i instride(from: m -1, through: l, by:-1){
curSum += nums[i]
leftSum =max(leftSum, curSum)}
curSum =0for i instride(from: m +1, to: r +1, by:1){
curSum += nums[i]
rightSum =max(rightSum, curSum)}returnmax(dfs(l, m -1),dfs(m +1, r), leftSum + nums[m]+ rightSum)}returndfs(0, nums.count -1)}}
Time & Space Complexity
Time complexity: O(nlogn)
Space complexity: O(logn)
Common Pitfalls
Initializing the Result to Zero
When all elements in the array are negative, the maximum subarray sum is the largest negative number, not zero. Initializing maxSum to 0 instead of nums[0] (or negative infinity) causes the algorithm to incorrectly return 0 for all-negative arrays. Always initialize with the first element or a sufficiently small value.
Resetting Current Sum at the Wrong Time
In Kadane's algorithm, you should reset curSum to zero when it becomes negative, not when it becomes less than the current element. The condition if (curSum < 0) curSum = 0 should come before adding the current element, not after. Placing this check incorrectly changes when subarrays restart and produces wrong results.