Find Maximum Subarray Divide and Conquer in DSA C# - Time & Space Complexity
We want to know how the time needed to find the maximum subarray grows as the input array gets bigger.
How does the divide and conquer method scale with larger arrays?
Analyze the time complexity of the following code snippet.
int FindMaxCrossingSubarray(int[] arr, int low, int mid, int high) {
int leftSum = int.MinValue, sum = 0;
for (int i = mid; i >= low; i--) {
sum += arr[i];
if (sum > leftSum) leftSum = sum;
}
int rightSum = int.MinValue;
sum = 0;
for (int j = mid + 1; j <= high; j++) {
sum += arr[j];
if (sum > rightSum) rightSum = sum;
}
return leftSum + rightSum;
}
int FindMaxSubarray(int[] arr, int low, int high) {
if (low == high) return arr[low];
int mid = (low + high) / 2;
int leftMax = FindMaxSubarray(arr, low, mid);
int rightMax = FindMaxSubarray(arr, mid + 1, high);
int crossMax = FindMaxCrossingSubarray(arr, low, mid, high);
return Math.Max(Math.Max(leftMax, rightMax), crossMax);
}
This code finds the maximum sum of a contiguous subarray using divide and conquer.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive calls splitting the array into halves.
- How many times: Each recursive call splits the array into two parts until size 1.
- Additional operation: The crossing subarray check loops over elements around the middle once per call.
Each time we split the array, we do two recursive calls on half the size and one linear scan around the middle.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 * log 10 ≈ 33 |
| 100 | About 100 * log 100 ≈ 664 |
| 1000 | About 1000 * log 1000 ≈ 9966 |
Pattern observation: The operations grow a bit more than linearly, roughly n times the number of splits (log n).
Time Complexity: O(n log n)
This means the time needed grows a little faster than the size of the input, because of splitting and merging steps.
[X] Wrong: "Since the array is split in half each time, the time complexity must be O(log n)."
[OK] Correct: Each split does extra work scanning around the middle, which takes linear time, so total time is more than just O(log n).
Understanding this time complexity helps you explain how divide and conquer algorithms balance splitting and combining work efficiently.
"What if the crossing subarray check was done in constant time instead of linear 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 subproblems
Find max subarray in left half, right half, and crossing the middle, then take the maximum of these three.Final Answer:
Split array, find max left, right, crossing, then combine -> Option DQuick Check:
Divide and conquer = split and combine max subarrays [OK]
- Thinking sorting helps find max subarray sum
- Using brute force sum of all subarrays
- Confusing divide and conquer with sliding window
Solution
Step 1: Identify base case for recursion
When the array has only one element, that element itself is the max subarray sum.Step 2: Return the single element value
Return the value of that single element as the maximum sum.Final Answer:
Return single element when array length is 1 -> Option BQuick Check:
Base case = single element value [OK]
- Returning 0 for single element array
- Returning sum of two elements as base case
- Not defining a base case causing infinite recursion
int[] arr = { -2, 1, -3, 4, -1, 2, 1, -5, 4 };
int maxSum = FindMaxSubarray(arr, 0, arr.Length - 1);
Console.WriteLine(maxSum);
int FindMaxSubarray(int[] a, int left, int right) {
if (left == right) return a[left];
int mid = (left + right) / 2;
int leftMax = FindMaxSubarray(a, left, mid);
int rightMax = FindMaxSubarray(a, mid + 1, right);
int crossMax = FindMaxCrossingSubarray(a, left, mid, right);
return Math.Max(Math.Max(leftMax, rightMax), crossMax);
}
int FindMaxCrossingSubarray(int[] a, int left, int mid, int right) {
int leftSum = int.MinValue, sum = 0;
for (int i = mid; i >= left; i--) {
sum += a[i];
if (sum > leftSum) leftSum = sum;
}
int rightSum = int.MinValue;
sum = 0;
for (int j = mid + 1; j <= right; j++) {
sum += a[j];
if (sum > rightSum) rightSum = sum;
}
return leftSum + rightSum;
}Solution
Step 1: Identify the maximum subarray sum
The array is [-2, 1, -3, 4, -1, 2, 1, -5, 4]. The subarray [4, -1, 2, 1] (indices 3-6) sums to 6, which is the maximum.Step 2: Trace the code execution
Split at mid=4: leftMax (0-4) = 4, rightMax (5-8) = 4, crossMax = 6 ([3-6]). Returns Math.Max(4, 4, 6) = 6.Final Answer:
6 -> Option AQuick Check:
max(leftMax=4, rightMax=4, crossMax=6) = 6 [OK]
- Miscomputing crossing sum
- Confusing max subarray with max element
- Ignoring negative numbers impact
int FindMaxCrossingSubarray(int[] a, int left, int mid, int right) {
int leftSum = 0, sum = 0;
for (int i = mid; i >= left; i--) {
sum += a[i];
if (sum > leftSum) leftSum = sum;
}
int rightSum = 0;
sum = 0;
for (int j = mid + 1; j <= right; j++) {
sum += a[j];
if (sum > rightSum) rightSum = sum;
}
return leftSum + rightSum;
}Solution
Step 1: Check initialization of leftSum and rightSum
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.MinValue
Initialize leftSum and rightSum to int.MinValue to correctly track max sums even if negative.Final Answer:
Initialize leftSum and rightSum to int.MinValue -> Option AQuick Check:
Init max sums to int.MinValue to handle negatives [OK]
- Initializing max sums to 0 causing wrong results
- Resetting sum incorrectly between loops
- Returning sum instead of max in crossing function
int[] arr = { -1, -2, -3, -4 }, what will the divide and conquer algorithm return as the maximum subarray sum?Solution
Step 1: Analyze array with all negative numbers
All elements are negative, so max subarray is the single largest element.Step 2: Identify largest element
The largest element is -1, which is the max subarray sum.Final Answer:
-1 -> Option CQuick Check:
Max subarray in negatives = max element [OK]
- Returning 0 instead of max negative element
- Summing all negatives incorrectly
- Assuming empty subarray sum is allowed
Ready to prove it?
Pass the test and this pattern moves unknown
