Find Maximum Subarray Divide and Conquer in DSA C - Time & Space Complexity
We want to understand how the time needed to find the maximum subarray grows as the input array gets bigger.
Specifically, how the divide and conquer method affects the work done.
Analyze the time complexity of the following code snippet.
int maxCrossingSum(int arr[], int left, int mid, int right) {
int sum = 0, left_sum = INT_MIN;
for (int i = mid; i >= left; i--) {
sum += arr[i];
if (sum > left_sum) left_sum = sum;
}
sum = 0;
int right_sum = INT_MIN;
for (int i = mid + 1; i <= right; i++) {
sum += arr[i];
if (sum > right_sum) right_sum = sum;
}
return left_sum + right_sum;
}
int maxSubArraySum(int arr[], int left, int right) {
if (left == right) return arr[left];
int mid = (left + right) / 2;
int left_max = maxSubArraySum(arr, left, mid);
int right_max = maxSubArraySum(arr, mid + 1, right);
int cross_max = maxCrossingSum(arr, left, mid, right);
return (left_max > right_max) ? (left_max > cross_max ? left_max : cross_max) : (right_max > cross_max ? right_max : cross_max);
}
This code finds the maximum sum of a subarray using divide and conquer by splitting the array and combining results.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive calls splitting the array into halves.
- How many times: Each level splits the array into two parts, so recursion depth is about log n.
- Secondary operation: The maxCrossingSum function loops over parts of the array crossing the middle.
- How many times: At each recursion level, maxCrossingSum scans parts of the array once, totaling n work per level.
At each level, the total work scanning the array is about n, and the number of levels is about log n.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 * 4 = 40 |
| 100 | About 100 * 7 = 700 |
| 1000 | About 1000 * 10 = 10,000 |
Pattern observation: Operations grow roughly by n times log n, meaning work grows faster than linear but slower than quadratic.
Time Complexity: O(n log n)
This means the time needed grows a bit faster than the size of the input, but not as fast as checking every pair.
[X] Wrong: "Since the array is split in half each time, the time complexity is O(log n)."
[OK] Correct: Although the array splits reduce the problem size, the crossing sum loops over parts of the array at each level, adding up to n work per level, so total work is more than just log n.
Understanding this divide and conquer approach helps you see how breaking problems down and combining results affects performance, a key skill in many coding challenges.
"What if we replaced the maxCrossingSum function with a method that scans the entire array each time? How would the time complexity change?"
Practice
Divide and Conquer approach to find the maximum subarray sum?Solution
Step 1: Understand divide and conquer strategy
The array is split into two halves recursively to simplify the problem.Step 2: Combine results from left, right, and crossing subarrays
We find max subarray sums in left half, right half, and subarrays crossing the middle, then take the maximum of these.Final Answer:
Divide the array into two halves, find max subarray in left, right, and crossing middle, then combine results -> Option CQuick Check:
Divide and conquer = split, solve, combine [OK]
- Thinking sorting helps find max subarray sum
- Ignoring subarrays crossing the middle
- Trying to sum all subarrays directly
Solution
Step 1: Identify base case meaning
When the subarray has only one element (low equals high), the max subarray sum is that element itself.Step 2: Match base case condition
The conditionif (low == high) return arr[low];correctly returns the single element's value.Final Answer:
if (low == high) return arr[low]; -> Option DQuick Check:
Single element subarray returns element value [OK]
- Returning 0 when low == high
- Using incorrect comparison operators
- Returning sum of two elements instead of one
int arr[] = {-2, 1, -3, 4, -1, 2, 1, -5, 4};
int result = maxSubArray(arr, 0, 8);
printf("%d", result);
Assume maxSubArray is correctly implemented divide and conquer function.Solution
Step 1: Identify max subarray in given array
The maximum subarray is [4, -1, 2, 1] with sum 4 + (-1) + 2 + 1 = 6, but check if including more elements helps.Step 2: Check if extending subarray increases sum
Including the element before 4 is -3 (reduces sum), after 1 is -5 (reduces sum), so max sum is 6.Final Answer:
6 -> Option AQuick Check:
Max subarray sum = 6 [OK]
- Counting non-continuous elements
- Miscomputing sums with negative numbers
- Assuming max element alone is answer
int maxCrossingSum(int arr[], int low, int mid, int high) {
int left_sum = 0, sum = 0;
for (int i = mid; i >= low; i--) {
sum += arr[i];
if (sum > left_sum)
left_sum = sum;
}
int right_sum = 0;
sum = 0;
for (int i = mid + 1; i <= high; i++) {
sum += arr[i];
if (sum > right_sum)
right_sum = sum;
}
return left_sum + right_sum;
}Solution
Step 1: Understand initialization of sums
Initializing left_sum and right_sum to 0 causes errors if all numbers are negative, as max sum could be less than 0.Step 2: Correct initialization
They should be initialized to the smallest integer (INT_MIN) to correctly track max sums even if negative.Final Answer:
left_sum and right_sum should be initialized to INT_MIN, not 0 -> Option AQuick Check:
Initialize max sums to INT_MIN to handle negatives [OK]
- Initializing max sums to zero causes wrong results
- Not resetting sum variable properly
- Incorrect loop ranges
arr = [-1, -2, -3, -4], what will the divide and conquer max subarray function return and why?Solution
Step 1: Analyze array with all negative numbers
All elements are negative, so the max subarray is the one with the least negative value (largest number).Step 2: Identify max element
The largest element is -1, so max subarray sum is -1 (single element subarray).Final Answer:
-1 because the max subarray is the single largest element -> Option BQuick Check:
Max subarray in negatives = max single element [OK]
- Assuming sum of all negatives is max
- Considering empty subarray sum as zero incorrectly
- Picking last element without comparison
Ready to prove it?
Pass the test and this pattern moves unknown
