Merge Sort Algorithm in DSA C# - Time & Space Complexity
We want to understand how the time taken by merge sort changes as the list size grows.
How does the number of steps grow when sorting bigger lists?
Analyze the time complexity of the following code snippet.
public void MergeSort(int[] array, int left, int right) {
if (left >= right) return;
int mid = (left + right) / 2;
MergeSort(array, left, mid);
MergeSort(array, mid + 1, right);
Merge(array, left, mid, right);
}
void Merge(int[] array, int left, int mid, int right) {
int[] temp = new int[right - left + 1];
int i = left, j = mid + 1, k = 0;
while (i <= mid && j <= right) {
temp[k++] = (array[i] <= array[j]) ? array[i++] : array[j++];
}
while (i <= mid) temp[k++] = array[i++];
while (j <= right) temp[k++] = array[j++];
for (int m = 0; m < temp.Length; m++) {
array[left + m] = temp[m];
}
}
This code sorts an array by dividing it into halves, sorting each half, and then merging 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 recursively until single elements remain, then merged back up.
- The merge step loops through elements to combine two sorted halves.
Each split divides the list in half, creating layers of work. At each layer, merging all parts takes about the same total steps as the size of the list.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 40 steps |
| 100 | About 700 steps |
| 1000 | About 10,000 steps |
Pattern observation: The steps grow a bit faster than just doubling; they grow roughly like n times log n.
Time Complexity: O(n log n)
This means if the list size doubles, the work grows a little more than double, but much less than square.
[X] Wrong: "Merge sort is as slow as bubble sort because it compares elements repeatedly."
[OK] Correct: Merge sort smartly splits the list and merges sorted parts, so it does fewer total comparisons than bubble sort, which compares every pair repeatedly.
Understanding merge sort's time complexity shows you can analyze recursive divide-and-conquer algorithms, a key skill in many coding challenges.
"What if we changed the merge step to use extra space only once for the whole array instead of for each merge? How would the time complexity change?"
Practice
Merge Sort algorithm?Solution
Step 1: Understand the divide and conquer approach
Merge Sort splits the list into two halves recursively until each sublist has one element.Step 2: Merge sorted halves
Then it merges these small sorted lists back together in order to form a sorted list.Final Answer:
Divide the list into halves, sort each half, then merge them -> Option BQuick Check:
Merge Sort = Divide and conquer [OK]
- Confusing Merge Sort with Bubble Sort
- Thinking it sorts by swapping adjacent elements
- Believing it sorts by inserting elements one by one
Solution
Step 1: Identify correct parameter types and names
The merge function typically takes the array and three indices: left, mid, and right to merge two sorted halves.Step 2: Check C# syntax for method declaration
In C#, arrays are declared asint[] arrand the function returns void because it modifies the array in place.Final Answer:
void Merge(int[] arr, int left, int mid, int right) -> Option AQuick Check:
Correct signature = void Merge(int[] arr, int left, int mid, int right) [OK]
- Using incorrect return type (int instead of void)
- Wrong parameter types or order
- Using lowercase function names in C#
[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 to the array [4, 1, 3, 2]
Split into [4,1] and [3,2], sort each half to [1,4] and [2,3].Step 2: Merge the two sorted halves
Merging [1,4] and [2,3] results in [1, 2, 3, 4].Final Answer:
1, 2, 3, 4 -> Option CQuick Check:
Sorted array = 1, 2, 3, 4 [OK]
- Confusing merge order and producing unsorted output
- Not splitting array correctly
- Printing before sorting completes
void Merge(int[] arr, int left, int mid, int right) {
int n1 = mid - left + 1;
int n2 = right - mid;
int[] L = new int[n1];
int[] R = new int[n2];
for (int i = 0; i < n1; i++) L[i] = arr[left + i];
for (int j = 0; j < n2; j++) R[j] = arr[mid + 1 + j];
// merging logic follows
}Solution
Step 1: Check array size calculations
The size of the left array should bemid - left + 1to include the mid element; the right array size is correct asright - mid.Step 2: Analyze loop conditions for copying elements
Loops should use<to avoid out of bounds errors.Final Answer:
Incorrect array sizes for L and R -> Option AQuick Check:
Left array size must be mid - left + 1 [OK]
- Using <= causes index out of range errors
- Miscalculating array sizes
- Confusing mid index offsets
Solution
Step 1: Understand stability in sorting
A stable sort keeps equal elements in the same order as original.Step 2: Modify merge step to preserve order
When merging, if elements are equal, always pick from the left subarray first to keep original order.Final Answer:
When merging, if elements are equal, take element from left subarray first -> Option DQuick Check:
Stable merge = pick left element first on ties [OK]
- Removing duplicates before sorting changes data
- Assuming Quick Sort is stable (it is not)
- Sorting duplicates separately after merge
Ready to prove it?
Pass the test and this pattern moves unknown
