Merge Sort
Solve this ProblemTest Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
0 ≤ arr.length ≤ 200 - ◆
-1000 ≤ arr[i] ≤ 1000 - ◆
Sort in non-decreasing order
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
Approach & Solutions
Brute Force — Fresh Array at Every Merge
GoodSplit the array in half, recursively sort each half, then merge the two sorted halves back together. The natural way to write this splits by slicing out brand-new left and right arrays at every single recursive call, and merge() builds yet another new array to hold the result. It's correct and easy to follow, but across all the levels of recursion, the total memory allocated for all those throwaway sub-arrays adds up to more than the O(n) a merge sort actually needs.
O(n log n)O(n log n)1class Solution {
2 public int[] mergeSort(int[] arr) {
3 if (arr.length <= 1) return arr;
4 int mid = arr.length / 2;
5 int[] left = mergeSort(Arrays.copyOfRange(arr, 0, mid));
6 int[] right = mergeSort(Arrays.copyOfRange(arr, mid, arr.length));
7 return merge(left, right);
8 }
9
10 private int[] merge(int[] left, int[] right) {
11 int[] result = new int[left.length + right.length];
12 int i = 0, j = 0, k = 0;
13 while (i < left.length && j < right.length) {
14 if (left[i] <= right[j]) {
15 result[k++] = left[i++];
16 } else {
17 result[k++] = right[j++];
18 }
19 }
20 while (i < left.length) result[k++] = left[i++];
21 while (j < right.length) result[k++] = right[j++];
22 return result;
23 }
24}Optimal — One Reused Auxiliary Buffer
OptimalSame divide-and-conquer idea, same time complexity — but allocate exactly one auxiliary array up front, and pass it down through every recursive call by reference. Recursion now works on index ranges (lo, hi) into the original array instead of slicing out new sub-arrays, and every merge copies its range into the shared aux buffer and merges straight back into arr in place. Only one extra array ever exists, no matter how deep the recursion goes.
O(n log n)O(n)1class Solution {
2 public int[] mergeSort(int[] arr) {
3 int n = arr.length;
4 int[] aux = new int[n];
5 sort(arr, aux, 0, n - 1);
6 return arr;
7 }
8
9 private void sort(int[] arr, int[] aux, int lo, int hi) {
10 if (lo >= hi) return;
11 int mid = lo + (hi - lo) / 2;
12 sort(arr, aux, lo, mid);
13 sort(arr, aux, mid + 1, hi);
14 merge(arr, aux, lo, mid, hi);
15 }
16
17 private void merge(int[] arr, int[] aux, int lo, int mid, int hi) {
18 for (int k = lo; k <= hi; k++) {
19 aux[k] = arr[k];
20 }
21 int i = lo, j = mid + 1;
22 for (int k = lo; k <= hi; k++) {
23 if (i > mid) {
24 arr[k] = aux[j++];
25 } else if (j > hi) {
26 arr[k] = aux[i++];
27 } else if (aux[i] <= aux[j]) {
28 arr[k] = aux[i++];
29 } else {
30 arr[k] = aux[j++];
31 }
32 }
33 }
34}