Merge Sort as Divide and Conquer in DSA C# - Time & Space Complexity
We want to understand how the time needed to sort a list grows as the list gets bigger using merge sort.
How does breaking the problem into smaller parts affect the total work?
Analyze the time complexity of the following code snippet.
public void MergeSort(int[] arr, int left, int right)
{
if (left >= right) return;
int mid = (left + right) / 2;
MergeSort(arr, left, mid);
MergeSort(arr, mid + 1, right);
Merge(arr, left, mid, right);
}
// Merge method combines two sorted halves
This code splits the array into halves, sorts each half, then merges them back together.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive splitting and merging of subarrays.
- How many times: The array is split into halves until single elements remain, then merged back up.
Each split divides the array in half, and merging takes time proportional to the size of the parts.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 40 merges and splits combined |
| 100 | About 700 merges and splits combined |
| 1000 | About 10,000 merges and splits combined |
Pattern observation: The work grows a bit faster than just doubling; it grows like n times the number of splits (log n).
Time Complexity: O(n log n)
This means the time grows proportionally to the size of the list times how many times it can be split in half.
[X] Wrong: "Merge sort is just like bubble sort and takes n squared time."
[OK] Correct: Merge sort splits the list and merges efficiently, so it avoids repeated comparisons that bubble sort does.
Understanding merge sort's time complexity shows you can analyze divide and conquer methods, a key skill in many coding challenges.
"What if we changed the merge step to use extra space inefficiently? How would that affect the time complexity?"
Practice
Merge Sort algorithm?Solution
Step 1: Understand divide and conquer
Merge Sort splits the list into smaller parts to handle sorting easily.Step 2: Merge sorted parts
After sorting smaller parts, it merges them to get the final sorted list.Final Answer:
Divide the list into smaller parts, sort them, then merge back -> Option BQuick Check:
Merge Sort = Divide and conquer sorting [OK]
- Confusing Merge Sort with Bubble Sort
- Thinking Merge Sort sorts in place without merging
- Mixing up Merge Sort with Quick Sort
Solution
Step 1: Identify merge function purpose
Merge combines two sorted parts, so it needs array and indices for left, mid, right.Step 2: Check correct signature
void Merge(int[] arr, int left, int mid, int right) matches void return type and parameters for merging parts.Final Answer:
void Merge(int[] arr, int left, int mid, int right) -> Option AQuick Check:
Merge function signature = void Merge(int[] arr, int left, int mid, int right) [OK]
- Using return type int instead of void for merge
- Confusing merge with mergeSort function signature
- Wrong parameter names or missing mid index
{4, 1, 3, 2}?
int[] arr = {4, 1, 3, 2};
MergeSort(arr, 0, arr.Length - 1);
Console.WriteLine(string.Join(", ", arr));Solution
Step 1: Apply Merge Sort on array {4, 1, 3, 2}
Split into {4,1} and {3,2}, sort each to {1,4} and {2,3}.Step 2: Merge sorted halves
Merge {1,4} and {2,3} to get fully sorted {1,2,3,4}.Final Answer:
1, 2, 3, 4 -> Option CQuick Check:
Sorted array = 1, 2, 3, 4 [OK]
- Confusing merge step order
- Assuming original order remains
- Mixing up indices during merge
void MergeSort(int[] arr, int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
MergeSort(arr, left, mid);
MergeSort(arr, mid, right);
Merge(arr, left, mid, right);
}
}Solution
Step 1: Check recursive calls ranges
Second call uses mid as start, but it should start from mid + 1 to avoid overlap.Step 2: Correct recursive call
Change second call to MergeSort(arr, mid + 1, right) to cover right half properly.Final Answer:
The second recursive call should be MergeSort(arr, mid + 1, right) -> Option AQuick Check:
Correct recursive ranges avoid overlap [OK]
- Using mid instead of mid + 1 for right half
- Calling merge before sorting halves
- Wrong base condition causing infinite recursion
Solution
Step 1: Understand optimization for duplicates
If left half's max ≤ right half's min, they are already sorted relative to each other.Step 2: Skip merge if condition met
By checking this, we avoid merging which saves time on duplicates.Final Answer:
Check if the last element of left half is less or equal to first element of right half before merging -> Option DQuick Check:
Skip merge if halves already ordered [OK]
- Removing duplicates before sorting changes data
- Skipping sorting halves based on duplicates
- Merging only equal sized halves is incorrect
Ready to prove it?
Pass the test and this pattern moves unknown
