Divide and Conquer Strategy and Recurrence Relations in DSA C# - Time & Space Complexity
Divide and conquer breaks a big problem into smaller parts, solves each part, then combines results.
We want to know how the time to solve grows as the problem size grows.
Analyze the time complexity of the following code snippet.
void DivideAndConquer(int n) {
if (n <= 1) return;
DivideAndConquer(n / 2);
DivideAndConquer(n / 2);
// constant work here
}
This code splits the problem into two halves, solves each recursively, then does a small fixed amount of work.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Two recursive calls each on half the input size.
- How many times: Recursion continues until input size reduces to 1.
Each call splits into two smaller calls, doubling the number of calls as size halves.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 19 calls |
| 100 | About 199 calls |
| 1000 | About 1999 calls |
Pattern observation: Operations roughly double each time input size doubles, growing linearly with n.
Time Complexity: O(n)
This means the total work grows directly in proportion to the input size.
[X] Wrong: "Because it calls itself twice, time is O(2^n)."
[OK] Correct: Each call works on half the input, so the number of calls grows linearly, not exponentially.
Understanding how dividing problems reduces work is a key skill for solving many algorithm challenges.
"What if the problem was divided into three parts instead of two? How would the time complexity change?"
Practice
Divide and Conquer strategy in algorithms?Solution
Step 1: Understand the divide and conquer approach
It splits a big problem into smaller parts that are easier to solve separately.Step 2: Combine the solutions of subproblems
After solving smaller parts, their results are combined to get the final answer.Final Answer:
Break the problem into smaller subproblems, solve them independently, then combine results -> Option AQuick Check:
Divide and conquer = split, solve, combine [OK]
- Confusing divide and conquer with brute force
- Thinking it processes elements sequentially only
- Mixing it up with dynamic programming
Solution
Step 1: Recall Merge Sort divides array into two halves
It splits the array into two parts, sorts each recursively.Step 2: Merge step takes linear time O(n)
After sorting halves, merging takes O(n) time.Final Answer:
T(n) = 2T(n/2) + O(n) -> Option BQuick Check:
Merge Sort recurrence = 2T(n/2) + n [OK]
- Using T(n-1) instead of T(n/2)
- Confusing merge cost as constant time
- Choosing wrong number of recursive calls
int SumArray(int[] arr, int start, int end) {
if (start == end) return arr[start];
int mid = (start + end) / 2;
return SumArray(arr, start, mid) + SumArray(arr, mid + 1, end);
}
int[] nums = {2, 4, 6, 8};
Console.WriteLine(SumArray(nums, 0, nums.Length - 1));Solution
Step 1: Understand the recursive sum function
The function splits the array into halves until one element remains, then sums back up.Step 2: Calculate sum of array elements
Sum = 2 + 4 + 6 + 8 = 20.Final Answer:
20 -> Option AQuick Check:
Sum of {2,4,6,8} = 20 [OK]
- Confusing mid calculation causing infinite recursion
- Forgetting base case when start == end
- Miscounting sum of elements
int MaxElement(int[] arr, int start, int end) {
if (start == end) return arr[start];
int mid = (start + end) / 2;
int leftMax = MaxElement(arr, start, mid);
int rightMax = MaxElement(arr, mid, end);
return Math.Max(leftMax, rightMax);
}Solution
Step 1: Analyze recursive calls for correct subarray ranges
The first call covers start to mid, so the second must cover mid+1 to end to avoid overlap.Step 2: Identify the off-by-one error
Using mid again in second call causes overlap and possible infinite recursion.Final Answer:
The second recursive call should be MaxElement(arr, mid + 1, end) -> Option CQuick Check:
Correct subarray split avoids overlap [OK]
- Using mid instead of mid+1 causing infinite recursion
- Changing base case incorrectly
- Replacing max with min mistakenly
T(n) = 3T(n/3) + n, which of the following is the correct time complexity using the Master Theorem?Solution
Step 1: Identify parameters a, b, and f(n)
Here, a=3, b=3, and f(n)=n.Step 2: Calculate log_b(a) and compare with f(n)
log_3(3) = 1, so f(n) = n = n^{log_b(a)}.Step 3: Apply Master Theorem case 2
Since f(n) = Theta(n^{log_b(a)}), time complexity is O(n).Final Answer:
O(n) -> Option DQuick Check:
Master theorem case 2 = O(n) [OK]
- Confusing log base or parameters a and b
- Choosing wrong Master Theorem case
- Ignoring the extra n term in recurrence
Ready to prove it?
Pass the test and this pattern moves unknown
