
Problem Statement
In this task, we're given an array of integers named nums
. Our goal is to identify a continuous subarray (meaning a sequence of one or more numbers in nums
) that has the maximum possible sum among all subarrays, and then return this maximum sum. The solution should efficiently handle varying sizes of nums
from just one element up to 100,000 elements, with individual element values ranging between -10,000 and 10,000.
Examples
Example 1
Input:
nums = [-2,1,-3,4,-1,2,1,-5,4]
Output:
6
Explanation:
The subarray [4,-1,2,1] has the largest sum 6.
Example 2
Input:
nums = [1]
Output:
1
Explanation:
The subarray [1] has the largest sum 1.
Example 3
Input:
nums = [5,4,-1,7,8]
Output:
23
Explanation:
The subarray [5,4,-1,7,8] has the largest sum 23.
Constraints
1 <= nums.length <= 105
-104 <= nums[i] <= 104
Approach and Intuition
The problem of finding the subarray with the maximum sum, also known as the "Maximum Subarray Problem", is a classic example that can be efficiently solved using Kadane's Algorithm. This algorithm leverages dynamic programming principles in a subtle manner. Here’s the intuition and approach step-by-step:
- Initialize two variables,
max_current
andmax_global
. Both are initially set to the first element ofnums
. - Start iterating from the second element of the array.
- For each element, decide whether to add it to the existing subarray sum (
max_current
) or start a new subarray sum with the current element as its first element. This decision is made by calculating:max_current = max(nums[i], max_current + nums[i])
- Update the global maximum if the current maximum is greater:
max_global = max(max_global, max_current)
- Continue this comparison until the end of the array.
By the end of one pass through the array, max_global
holds the maximum sum of any subarray.
Example Analysis:
- For
nums = [-2,1,-3,4,-1,2,1,-5,4]
:- Initiate
max_current
andmax_global
with -2. - As we proceed, when we reach element '4', the sum becomes more positive and updates
max_current
significantly. Continuing from there, despite minor drops due to negative numbers, the sum accumulated by [4,-1,2,1] becomes the highest, thus updatingmax_global
to 6.
- Initiate
- The singular element array
nums = [1]
straightaway reveals that when the array size is one, that single element is the result. - Similarly, for
nums = [5,4,-1,7,8]
, the entire array itself forms the maximum sum subarray with a sum of 23.
Through this approach, instead of examining sums of all possible subarrays explicitly — which would be computationally expensive — Kadane's algorithm smartly maintains and updates the running totals with linear complexity O(n), making it optimal for large inputs as defined by our constraints.
Solutions
- C++
- Java
- C
- JavaScript
- Python
class Solution {
private:
vector<int> elements;
public:
int maximumSubArray(vector<int>& nums) {
elements = nums;
return calculateSubarray(0, elements.size() - 1);
}
int calculateSubarray(int left, int right) {
if (left > right) {
return INT_MIN;
}
int midpoint = (left + right) / 2;
int sum = 0;
int maxLeftSum = 0;
int maxRightSum = 0;
for (int i = midpoint - 1; i >= left; i--) {
sum += elements[i];
maxLeftSum = max(maxLeftSum, sum);
}
sum = 0;
for (int i = midpoint + 1; i <= right; i++) {
sum += elements[i];
maxRightSum = max(maxRightSum, sum);
}
int maxCrossingSum = elements[midpoint] + maxLeftSum + maxRightSum;
int maxLeftHalf = calculateSubarray(left, midpoint - 1);
int maxRightHalf = calculateSubarray(midpoint + 1, right);
return max(maxCrossingSum, max(maxLeftHalf, maxRightHalf));
}
};
The solution provided is a C++ implementation for solving the Maximum Subarray problem, which aims to find the contiguous subarray (containing at least one number) which has the largest sum among all subarrays of a given array of integers.
The
Solution
class is designed with two main functions:maximumSubArray
is the public interface function which initializes theelements
vector with the input array and calls the recursivecalculateSubarray
function.calculateSubarray
is a private recursive function that computes the maximum sum of subarrays divided by a divide and conquer approach.
The divide and conquer strategy works by:
- Dividing the array into left, right, and middle parts.
- Recursively finding the maximum subarray sums for the left and the right halves.
- Finding the maximum subarray sum that crosses the middle element by adding the maximum sums from both sides of the middle point.
The recursion ends when the base case is reached, where the left index surpasses the right index, at which point the function returns a minimal integer value as no sum is possible.
This approach ensures all possible subarrays are considered. It uses a combination of linear iterations for crossing sums and recursive calls for left and right half sums, effectively navigating through the entire array to ensure that the maximum possible sum is computed.
The strategy efficiently handles array indexing and element access efficiently to minimize overheads and achieve optimal performance. The recursive depth and multiple indices are well managed to avoid confusion and ensure a systematic and clear subdivision of the problem at each step.
By comparing maximum sums across different sections of the array and combining them effectively, the solution guarantees that the highest subarray sum is obtained, handling even negative numbers correctly through comparison with zero and the use of
INT_MIN
to represent untenably low sums.
class Solution {
private int[] dataArray;
public int maxSequence(int[] data) {
dataArray = data;
return calculateMaxSubsequence(0, dataArray.length - 1);
}
private int calculateMaxSubsequence(int start, int end) {
if (start > end) {
return Integer.MIN_VALUE;
}
int middle = (start + end) / 2;
int sum = 0;
int maxLeft = 0;
int maxRight = 0;
for (int i = middle - 1; i >= start; i--) {
sum += dataArray[i];
maxLeft = Math.max(maxLeft, sum);
}
sum = 0;
for (int i = middle + 1; i <= end; i++) {
sum += dataArray[i];
maxRight = Math.max(maxRight, sum);
}
int maxCrossing = dataArray[middle] + maxLeft + maxRight;
int bestLeft = calculateMaxSubsequence(start, middle - 1);
int bestRight = calculateMaxSubsequence(middle + 1, end);
return Math.max(maxCrossing, Math.max(bestLeft, bestRight));
}
}
The provided Java solution is designed to find the maximum sum of any contiguous subarray within a given integer array. This problem is commonly solved using the "divide and conquer" approach, as illustrated in this implementation.
The solution consists of the Solution
class which contains two primary functions:
maxSequence(int[] data)
: This function initializes the data array and invokes the recursive functioncalculateMaxSubsequence
on the entire array.calculateMaxSubsequence(int start, int end)
: This function recursively divides the array into halves to find the maximum subarray sum. It calculates the maximum sums of the left and right subarrays as well as the sum of subarrays crossing the middle element, then returns the maximum of these three sums.
The recursive function uses the following steps to compute the solution:
- Determine the base case where if the
start
index exceeds theend
index, return the smallest possible integer value. - Calculate the middle index of the current segment of the array.
- Compute maximum sums for the left part ending at middle-1 and the right part starting at middle+1.
- Compute the maximum sum crossing the middle by adding maximum left and right sums to the middle element's value.
- Recursively find the maximum subarray sums for the left and right halves of the array.
- Return the maximum value among the left, right, and crossing subarrays.
This algorithm is efficient in solving the maximum subarray problem by breaking it down into smaller subproblems, solving each independently, and combining their solutions. The recursive division of the array ensures that each possible subarray is considered, while the use of maximum calculations consolidates these into the overall solution.
int maxArraySum(int* arr, int size) {
return bestSubArraySum(arr, 0, size - 1);
}
int bestSubArraySum(int* arr, int start, int end) {
if (start > end) {
return INT_MIN;
}
int middle = (start + end) / 2;
int sum = 0;
int maxLeftSum = 0;
int maxRightSum = 0;
for (int i = middle - 1; i >= start; i--) {
sum += arr[i];
maxLeftSum = fmax(maxLeftSum, sum);
}
sum = 0;
for (int i = middle + 1; i <= end; i++) {
sum += arr[i];
maxRightSum = fmax(maxRightSum, sum);
}
int maxCrossingSum = arr[middle] + maxLeftSum + maxRightSum;
int maxLeftPartSum = bestSubArraySum(arr, start, middle - 1);
int maxRightPartSum = bestSubArraySum(arr, middle + 1, end);
return fmax(maxCrossingSum, fmax(maxLeftPartSum, maxRightPartSum));
}
The provided C code implements a solution to the maximum subarray problem, which is to find the contiguous subarray with the maximum sum within a given array. This implementation uses a divide-and-conquer approach inspired by the classic algorithm.
Here's a breakdown of the solution technique:
- Two primary functions are defined,
maxArraySum
andbestSubArraySum
. - The
maxArraySum
function initiates the recursion. It passes the entire array and its boundaries (from0
tosize - 1
) to thebestSubArraySum
function. - The
bestSubArraySum
function recursively divides the given part of the array into halves until the subarrays contain only one element or no elements. - For each segment, a middle index is calculated, and from there, the function explores left to the boundary on the left and right to the boundary on the right to find the max possible sum contiguous subarrays in both directions.
- It calculates sums extending from the middle index outwards to both left and right bounds (
maxLeftSum
andmaxRightSum
respectively). This handles the case where the max subarray spans across the middle. - The function uses a supplementary loop to compute the sum when crossing from left to right, through the middle.
- Lastly, the main recursive function compares three values to determine the largest subarray sum for the combined segments:
- Subarray sum that lies completely in the left half (
maxLeftPartSum
) - Subarray sum that lies completely in the right half (
maxRightPartSum
) - Sum across the left and right subarrays through the middle element (
maxCrossingSum
)
- Subarray sum that lies completely in the left half (
The fmax
function from the math.h library supports finding the maximum of the competing sums effectively.
This divide-and-conquer approach essentially optimizes the search for the maximum subarray sum by breaking down the problem and combining solutions, which is more manageable and efficient in practice than simpler, brute-force methods.
var maxSubarraySum = function (arr) {
return calculateSubarray(arr, 0, arr.length - 1);
};
var calculateSubarray = function (arr, lft, rgt) {
if (lft > rgt) {
return -Infinity;
}
let middle = Math.floor((lft + rgt) / 2);
let currentSum = 0;
let maxLeftSubSum = 0;
let maxRightSubSum = 0;
for (let j = middle - 1; j >= lft; j--) {
currentSum += arr[j];
maxLeftSubSum = Math.max(maxLeftSubSum, currentSum);
}
currentSum = 0;
for (let j = middle + 1; j <= rgt; j++) {
currentSum += arr[j];
maxRightSubSum = Math.max(maxRightSubSum, currentSum);
}
let maxCrossSum = arr[middle] + maxLeftSubSum + maxRightSubSum;
let maxSubSumLeft = calculateSubarray(arr, lft, middle - 1);
let maxSubSumRight = calculateSubarray(arr, middle + 1, rgt);
return Math.max(maxCrossSum, Math.max(maxSubSumLeft, maxSubSumRight));
};
This summary discusses a solution for finding the maximum subarray sum using JavaScript. The provided implementation uses a divide and conquer approach, similar to the one used in the merge sort algorithm. It calculates the maximum sum of a subarray in an array of integers.
The
maxSubarraySum
function initiates the process and callscalculateSubarray
, passing the entire array and its boundaries as parameters.The
calculateSubarray
function finds the maximum subarray sum recursively:- It splits the array into two halves around a middle index.
- The function considers three cases for the maximum subarray sum:
- Maximum subarray sum in the left half.
- Maximum subarray sum in the right half.
- Maximum subarray sum that crosses the middle element combining elements from both halves.
- For the crossing sum, the algorithm calculates the maximum sums possible from the middle to both ends of the current subarray segment.
- It uses these calculations, including contributions from both halves of the array, to determine the maximum sum crossing the middle.
The recursive division continues until the base case where the sub-array has fewer elements, and the solution to each smaller problem combines to solve the larger problem.
It uses
Math.max
to determine the overall maximum sum among the left, right, and crossing sums.This recursive division allows the algorithm to efficiently tackle the problem, with each level of recursion breaking down the problem into smaller and easier-to-solve segments.
The solution flexibly handles varying input sizes and efficiently calculates required values, demonstrating the power of recursive algorithms in solving complex problems.
class Solution:
def findMaximumSubArray(self, arr: List[int]) -> int:
def calculateMaxSubArray(seq, start, end):
if start > end:
return float('-inf')
center = (start + end) // 2
sum_current = max_left = max_right = 0
for index in range(center - 1, start - 1, -1):
sum_current += seq[index]
max_left = max(max_left, sum_current)
sum_current = 0
for index in range(center + 1, end + 1):
sum_current += seq[index]
max_right = max(max_right, sum_current)
max_combined = seq[center] + max_left + max_right
left_part_max = calculateMaxSubArray(seq, start, center - 1)
right_part_max = calculateMaxSubArray(seq, center + 1, end)
return max(max_combined, left_part_max, right_part_max)
return calculateMaxSubArray(arr, 0, len(arr) - 1)
The provided Python code implements a solution to finding the maximum sum subarray using a recursive approach, specifically a divide and conquer algorithm.
The function
findMaximumSubArray
is defined to work on an input list of integers.Inside this function, a nested helper function
calculateMaxSubArray
is defined, which handles the recursion and calculation of the maximum sum subarray.The
calculateMaxSubArray
function takes three parameters:seq
(the list of integers),start
(starting index of the subarray), andend
(ending index of the subarray).If the
start
index is greater than theend
index, it returns negative infinity, representing an invalid subarray.The function calculates the center of the sequence and initializes variables to store current sums and maximum sums for the left and right sections around the center.
It then iterates both leftwards and rightwards from the center to find maximum subarrays that include the center element.
The maximum combined sum including the center, left maximum, and right maximum is stored in
max_combined
.Recursively, the function finds the maximum subarrays for the left and right halves, excluding the center.
Finally, the maximum of three potential maximum values (
max_combined
, the result from the left partition, and the result from the right partition) is returned.The top-level call initiates the process with the whole array from index 0 to
len(arr) - 1
.
This code effectively breaks down the problem into smaller subproblems, handles them individually, and then combines results to achieve the maximum sum subarray. Ensure input arrays are non-empty to avoid unexpected behavior due to the recursive structure.
No comments yet.