0% found this document useful (0 votes)
32 views11 pages

Maximum Subarray Sum Algorithms

DAA

Uploaded by

jainsy
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
32 views11 pages

Maximum Subarray Sum Algorithms

DAA

Uploaded by

jainsy
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Maximum Subarray Sum

Problem statement:
Given an array of both positive and negative integers, find the sum of contiguous subarray
of numbers which has largest sum
Ex:
{-2, -5, 6, -2, -3, 1, 5, -6}, then the maximum subarray sum is 7

Naïve Method:
• Using two loops.
• For every element in outer loop, the inner loop finds the max. sum possible
Compare the max. sum w.r.t. each element of outer loop with overall maximum
• Return overall maximum
Complexity: O(n2)

D.S. Adane, School of CSE, RBU, Nagpur 2


Kadane’s Method
Traverse over the array from left to right and for each element, find the maximum
sum among all subarrays ending at that element
The result will be the maximum of all these values
Central Idea:
To calculate the maximum sum of subarray ending at current element, say
Max_End, we can use the maximum sum ending at the previous element. So for
any element, we have two choices:
1. Extend the maximum sum subarray ending at the previous element by adding
the current element to it. If the maximum subarray sum ending at the previous
index is positive, then it is always better to extend the subarray.
2. Start a new subarray starting from the current element. If the maximum
subarray sum ending at the previous index is negative, it is always better to
start a new subarray from the current element.

D.S. Adane, School of CSE, RBU, Nagpur 3


Thus,
Max_End at index i = max(Max_End at index (i-1) + arr[i], arr[i])
Maximum of Max_End at any index is the answer
Algo:
int max_Subarray_Sum(int arr[], int size) {
int Max = arr[0]; // Overall Maximum
int Max_End = arr[0]; // Used for updation of list giving Maximum
for (int i = 1; i < size; i++) {
// Extend the maximum sum subarray ending at index i - 1 or
// starting a new subarray from index i
Max_End = (Max_End + arr[i] > arr[i]) ? Max_End + arr[i] : arr[i]);
// Update Max if maximum subarray sum ending at index i > Max
Max = (Max > Max_End) ? Max : Max_End;
}
return Max;
}
Complexity: O(n)

D.S. Adane, School of CSE, RBU, Nagpur 4


• Ex:
0 1 2 3 4 5 6 7
• arr[] = {-2, -5, 6, -2, -3, 1, 5, -6}
• Max = -2, Max_End = -2;
• i=1 to 7
• i=1 => arr[1] + Max_End = -7=> Max_End = -5, Max = -2
• i=2 => arr[2] + Max_End = 1 => Max_End = 6, Max = 6
• i=3 => arr[3] + Max_End = 4 => Max_End = 4, Max = 6
• i=4 => arr[4] + Max_End = 1 => Max_End = 1, Max = 6
• i=5 => arr[5] + Max_End = 2 => Max_End = 2, Max = 6
• i=6 => arr[6] + Max_End = 7 => Max_End = 7, Max = 7
• i=7 => arr[7] + Max_End = 1 => Max_End = 1, Max = 7
Return Max (7)

D.S. Adane, School of CSE, RBU, Nagpur 5


Divide and Conquer
• Can we apply Divide and Conquer to the problem to obtain better
complexity??
• Let us see….
• Steps:
• Divide the given array in two halves
• Return the maximum of following three
• Maximum subarray sum in left half (Make a recursive call)
• Maximum subarray sum in right half (Make a recursive call)
• Maximum subarray sum such that the subarray crosses the midpoint

D.S. Adane, School of CSE, RBU, Nagpur 6


• Algorithm:
int maxSubArraySum(int arr[], int l, int h) {
// Invalid Range: low is greater than high
if (l > h)
return INT_MIN;
// Base Case: Only one element
if (l == h)
return arr[l];
int m = (l + h) / 2;
return max(maxSubArraySum(arr, l, m ),
maxSubArraySum(arr, m + 1, h),
maxCrossingSum(arr, l, h));
}
D.S. Adane, School of CSE, RBU, Nagpur 7
int maxCrossingSum(int arr[], int l, int m, int h) { // Include elements on left of mid.
int sum = 0;
int l_sum = INT_MIN;
for (int i = m; i >= l; i--) {
sum = sum + arr[i];
if (sum > l_sum)
l_sum = sum;
}
// Include elements on right of mid
sum = 0;
int r_sum = INT_MIN;
for (int i = m+1; i <= h; i++) {
sum = sum + arr[i];
if (sum > r_sum)
r_sum = sum;
}
return max(l_sum + r_sum , left_sum, right_sum);
}
D.S. Adane, School of CSE, RBU, Nagpur 8
• Ex:
Arr[]= 0 1 2 3 4 5 6 7
-2, -5, 6, -2, -3, 1, 5, -6 mid=(0+7)/2=4
(mid)
-2, -5, 6, -2 1, 5, -6
(List 1) (List 2)
mid=(0+3)/2=2 mid=(5+7)/2=6
-2, -5 -2 1 -6
(List 3) (List 4) (List 5) (List 6)
mid=(0+1)/2=1
-2
(List 7)

D.S. Adane, School of CSE, RBU, Nagpur 9


steps 0 1 2 3 4 5 6 7
1 -2, -5, 6, -2, -3, 1, 5, -6
2 -2, -5, 6, -2 1, 5, -6
mSAS returns -6
3 -2, -5 -2 1 -6
mSAS returns -2 -2 mSAS returns -2 mSAS returns 1

From steps 3 to 1, MaxCrossingSum() returns Max value


Step 3: -2 -5  lsum = -7; rsum = -5; csum = -7-5-(-5) = -7; Max= -5; MaxCrossingSum returns -5
Step 2: List 1: -5 6 -2 List 2: 1 5 -6
lsum = 1; rsum = 4; csum = 1+4-6 = -1 lsum = 6; rsum = -1; csum = 6-1-5 = 0
MaxCrossingSum returns 4 MaxCrossingSum returns 6
Step 1: List: 4 -3 6
lsum = 1; rsum = 3; csum = 1+3-(-3) = 7
MaxCrossingSum returns 7

D.S. Adane, School of CSE, RBU, Nagpur 10


• Complexity??
• Every instance calls mSAS() twice for left and right sublists and mCS is
called once
• T(n) = 2T(n/2) + n
= O(n log n)

D.S. Adane, School of CSE, RBU, Nagpur 11

Common questions

Powered by AI

The divide and conquer approach divides the array into two halves and recursively finds the maximum subarray sum for each half and across the midpoint, using the function maxCrossingSum for the latter. It has a time complexity of O(n log n) because it involves splitting the array and combining results. In contrast, Kadane's algorithm iterates through the array once, maintaining intermediate sums to continuously update the maximum, achieving a linear time complexity of O(n). Thus, Kadane’s algorithm is more efficient and simpler to implement .

The naive method involves using two nested loops to explore all possible contiguous subarrays within the given array. For each starting point in the outer loop, it calculates the sum of subarrays ending at each subsequent element in the inner loop and continuously updates the global maximum sum found. The primary drawback of this method is its quadratic time complexity, O(n^2), which makes it inefficient for large arrays .

When Kadane’s algorithm is applied to an array consisting entirely of negative numbers, it will result in the single highest value in the array, which is the least negative number. This is because the algorithm updates the maximum based on local conditions, and in a purely negative array, starting a new subarray at the least negative number provides the highest possible sum .

Kadane's algorithm updates the overall maximum subarray sum by comparing the current element's maximum subarray sum (Max_End) with the global maximum sum (Max) after processing each element. If Max_End computed for the current element is greater than Max, then Max is updated with Max_End. This ensures that by the time the iteration completes, Max holds the highest subarray sum encountered .

In Kadane's algorithm, starting a new subarray when the previous maximum sum is negative is efficient because any additional sum to a subarray with a negative total will reduce the potential maximum sum. Resetting provides a chance to exclude the negative influence and potentially include larger positive values starting from the current element, leading to a higher subarray sum in future calculations .

In the divide and conquer recursive function for finding the maximum subarray sum, the base case occurs when the subarray has only one element. If the starting and ending indices of the subarray are the same, the function simply returns the value of that single element because it is the maximum subarray sum by default .

It is theoretically challenging to modify the divide and conquer algorithm to achieve the same linear time complexity, O(n), as Kadane’s algorithm because its strategy inherently involves dividing the problem and processing each half separately before combining results. The division and recursive merging inherently require O(log n) levels of combination, each taking O(n) operations in the worst case, hence resulting in O(n log n). Kadane's method optimizes at every step linearly, inherently making it more suitable for such problems .

The maxCrossingSum function in the divide and conquer method calculates the maximum subarray sum that crosses the midpoint of a given subarray. It works by separately calculating the maximum sum of the left subarray ending at the midpoint and the right subarray starting just after the midpoint. The maximum crossing sum is the sum of these two maximums, plus any overlapping element if relevant. This operation is crucial as it provides a possible maximum that might not be fully contained within either half of the array, ensuring the overall maximum is identified .

Kadane's algorithm aims to find the maximum subarray sum by maintaining a running maximum sum that ends at each element, referred to as Max_End. At each element, you have two choices: extend the current subarray by adding the element if the previous sum (Max_End) was positive, or start a new subarray from the current element if the previous sum was negative. The maximum value of these sums as you traverse the array provides the maximum subarray sum .

For large arrays, the divide and conquer method is significantly more efficient than the naive method because it runs in O(n log n) time complexity compared to the O(n^2) complexity of the naive method. This improved performance arises from reducing the number of operations required by splitting the array and combining results, whereas the naive approach examines every possible subarray independently, leading to much greater computational expense .

You might also like