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 size increases.
How does the divide and conquer method affect the work done compared to checking all subarrays?
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 std::max({left_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: The array is split until single elements remain, about log n levels.
- Additional operation: At each level, the maxCrossingSum scans parts of the array once.
- Dominant operation: The combination step scanning around the middle index.
At each level, the array is split into two halves, and the crossing sum is calculated by scanning parts of the array.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 * log2(10) ≈ 33 |
| 100 | About 100 * log2(100) ≈ 664 |
| 1000 | About 1000 * log2(1000) ≈ 9966 |
Pattern observation: The work grows a bit faster than linear but much slower than quadratic, roughly n times log n.
Time Complexity: O(n log n)
This means the time needed grows a little more than directly proportional to the input size, multiplied by the number of times we split the array.
[X] Wrong: "Since the array is split in half each time, the time complexity must be O(log n)."
[OK] Correct: Each level does work scanning parts of the array, so the total work adds up to n times log n, not just log n.
Understanding this divide and conquer approach helps you think about breaking problems into smaller parts and combining results efficiently, a key skill in many coding challenges.
"What if we replaced the maxCrossingSum scanning with a constant time operation? 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.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 and combine max sums [OK]
- Thinking sorting helps find max subarray sum
- Ignoring subarrays crossing the middle
- Trying to check all subarrays without divide and conquer
Solution
Step 1: Identify base case for single element
When low equals high, the subarray has one element, so max sum is that element itself.Step 2: Check options for correct base case
if (low == high) return arr[low]; returns arr[low] when low == high, which is correct base case.Final Answer:
if (low == high) return arr[low]; -> Option DQuick Check:
Single element subarray max sum = element value [OK]
- Returning 0 for single element subarray
- Using incorrect comparison operators in base case
- Returning sum of two elements when only one element left
int arr[] = {-2, 1, -3, 4, -1, 2, 1, -5, 4};
int n = 9;
int maxCrossingSum(int arr[], int low, int mid, int high) {
int sum = 0, left_sum = INT_MIN;
for (int i = mid; i >= low; i--) {
sum += arr[i];
if (sum > left_sum) left_sum = sum;
}
sum = 0; int right_sum = INT_MIN;
for (int i = mid + 1; i <= high; i++) {
sum += arr[i];
if (sum > right_sum) right_sum = sum;
}
return left_sum + right_sum;
}
int maxSubArraySum(int arr[], int low, int high) {
if (low == high) return arr[low];
int mid = (low + high) / 2;
int left_max = maxSubArraySum(arr, low, mid);
int right_max = maxSubArraySum(arr, mid + 1, high);
int cross_max = maxCrossingSum(arr, low, mid, high);
return max(max(left_max, right_max), cross_max);
}
int result = maxSubArraySum(arr, 0, n - 1);
std::cout << result;Solution
Step 1: Identify the maximum subarray
The array is [-2, 1, -3, 4, -1, 2, 1, -5, 4]. The subarray [4, -1, 2, 1] (indices 3-6) sums to 6, the maximum.Step 2: Verify code execution
Top-level split: left_max=4, right_max=4, cross_max=6 (left suffix 4 + right prefix -1+2+1=2). Returns 6.Final Answer:
6 -> Option AQuick Check:
Max subarray sum = 6 [OK]
- Confusing max crossing sum with max overall sum
- Miscounting indices in loops
- Assuming max sum includes all positive numbers only
int maxCrossingSum(int arr[], int low, int mid, int high) {
int sum = 0, left_sum = 0;
for (int i = mid; i >= low; i--) {
sum += arr[i];
if (sum > left_sum) left_sum = sum;
}
sum = 0; int right_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: Check initialization of left_sum and right_sum
They are initialized to 0, which fails if all numbers are negative because max sum could be less than 0.Step 2: Correct initialization to INT_MIN
Initializing left_sum and right_sum to INT_MIN ensures negative sums are correctly handled.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 causing wrong results
- Incorrect loop directions
- Not resetting sum before right loop
arr = [-1, -2, -3, -4], what will the divide and conquer maximum subarray function return?Solution
Step 1: Understand max subarray with all negative numbers
When all numbers are negative, max subarray is the single largest element (least negative).Step 2: Find largest element in arr
Elements are -1, -2, -3, -4. The largest is -1.Final Answer:
-1 -> Option BQuick Check:
Max subarray in negatives = max element [OK]
- Returning sum of all elements instead of max single element
- Returning zero incorrectly assuming empty subarray
- Ignoring negative values in max calculation
Ready to prove it?
Pass the test and this pattern moves unknown
