void merge(int arr[], int l, int m, int r) { int n1 = m - l + 1; int n2 = r - m; int L[n1], R[n2]; for (int i = 0; i < n1; i++) L[i] = arr[l + i]; for (int j = 0; j < n2; j++) R[j] = arr[m + 1 + j]; int i = 0, j = 0, k = l; while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k] = L[i]; i++; } else { arr[k] = R[j]; j++; } k++; } while (i < n1) { arr[k] = L[i]; i++; k++; } while (j < n2) { arr[k] = R[j]; j++; k++; } } void mergeSort(int arr[], int l, int r) { if (l < r) { int m = l + (r - l) / 2; mergeSort(arr, l, m); mergeSort(arr, m + 1, r); merge(arr, l, m, r); } } int main() { int arr[] = {4, 1, 3, 2}; int arr_size = sizeof(arr) / sizeof(arr[0]); mergeSort(arr, 0, arr_size - 1); for (int i = 0; i < arr_size; i++) { printf("%d ", arr[i]); } return 0; }
The merge sort splits the array into halves recursively until single elements remain, then merges them back in sorted order. The final sorted array is 1 2 3 4.
Merge sort divides the array into halves recursively (log n splits) and merges them (n operations per merge), resulting in O(n log n) time complexity.
void merge(int arr[], int l, int m, int r) { int n1 = m - l + 1; int n2 = r - m; int L[n1], R[n2]; for (int i = 0; i < n1; i++) L[i] = arr[l + i]; for (int j = 0; j < n2; j++) R[j] = arr[m + 1 + j]; int i = 0, j = 0, k = l; while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k] = L[i]; i++; } else { arr[k] = R[j]; j++; } k++; } while (i < n1) { arr[k] = L[i]; i++; k++; } while (j < n2) { arr[k] = R[j]; j++; k++; } }
The loop copying elements into L uses i <= n1 which goes one past the array size, causing out of bounds access.
During the merge step, when an element from the right half is placed before one from the left, it indicates inversions equal to the remaining elements in the left half.
Standard merge sort uses temporary arrays to hold halves during merging, requiring O(n) extra space. The recursion stack uses O(log n), but the dominant space is from these arrays.
