Sort an Array
Sort an array in O(n log n) using merge sort or randomized quicksort.
4 min read
sorting divide-conquer
Problem#
Sort nums ascending in O(n log n) without using built-in sort.
Examples#
[5,2,3,1]→[1,2,3,5]
Constraints#
1 <= nums.length <= 5 * 10^4.
Approach#
Top-down merge sort. Split, recurse, merge — classic divide and conquer.
Solution#
class Solution {public: vector<int> sortArray(vector<int>& nums) { vector<int> buf(nums.size()); mergeSort(nums, buf, 0, nums.size() - 1); return nums; }private: void mergeSort(vector<int>& a, vector<int>& buf, int lo, int hi) { if (lo >= hi) return; int mid = lo + (hi - lo) / 2; mergeSort(a, buf, lo, mid); mergeSort(a, buf, mid + 1, hi); int i = lo, j = mid + 1, k = lo; while (i <= mid && j <= hi) buf[k++] = a[i] <= a[j] ? a[i++] : a[j++]; while (i <= mid) buf[k++] = a[i++]; while (j <= hi) buf[k++] = a[j++]; for (int x = lo; x <= hi; ++x) a[x] = buf[x]; }};func sortArray(nums []int) []int { buf := make([]int, len(nums)) var mergeSort func(lo, hi int) mergeSort = func(lo, hi int) { if lo >= hi { return } mid := lo + (hi-lo)/2 mergeSort(lo, mid) mergeSort(mid+1, hi) i, j, k := lo, mid+1, lo for i <= mid && j <= hi { if nums[i] <= nums[j] { buf[k] = nums[i] i++ } else { buf[k] = nums[j] j++ } k++ } for i <= mid { buf[k] = nums[i] i++ k++ } for j <= hi { buf[k] = nums[j] j++ k++ } for x := lo; x <= hi; x++ { nums[x] = buf[x] } } mergeSort(0, len(nums)-1) return nums}from typing import List
class Solution: def sortArray(self, nums: List[int]) -> List[int]: buf = [0] * len(nums)
def merge_sort(lo: int, hi: int) -> None: if lo >= hi: return mid = lo + (hi - lo) // 2 merge_sort(lo, mid) merge_sort(mid + 1, hi) i, j, k = lo, mid + 1, lo while i <= mid and j <= hi: if nums[i] <= nums[j]: buf[k] = nums[i] i += 1 else: buf[k] = nums[j] j += 1 k += 1 while i <= mid: buf[k] = nums[i] i += 1 k += 1 while j <= hi: buf[k] = nums[j] j += 1 k += 1 for x in range(lo, hi + 1): nums[x] = buf[x]
merge_sort(0, len(nums) - 1) return numsfunction sortArray(nums) { const buf = new Array(nums.length); const mergeSort = (lo, hi) => { if (lo >= hi) return; const mid = lo + ((hi - lo) >> 1); mergeSort(lo, mid); mergeSort(mid + 1, hi); let i = lo, j = mid + 1, k = lo; while (i <= mid && j <= hi) { buf[k++] = nums[i] <= nums[j] ? nums[i++] : nums[j++]; } while (i <= mid) buf[k++] = nums[i++]; while (j <= hi) buf[k++] = nums[j++]; for (let x = lo; x <= hi; x++) nums[x] = buf[x]; }; mergeSort(0, nums.length - 1); return nums;}class Solution { private int[] buf;
private void mergeSort(int[] a, int lo, int hi) { if (lo >= hi) return; int mid = lo + (hi - lo) / 2; mergeSort(a, lo, mid); mergeSort(a, mid + 1, hi); int i = lo, j = mid + 1, k = lo; while (i <= mid && j <= hi) { buf[k++] = a[i] <= a[j] ? a[i++] : a[j++]; } while (i <= mid) buf[k++] = a[i++]; while (j <= hi) buf[k++] = a[j++]; for (int x = lo; x <= hi; x++) a[x] = buf[x]; }
public int[] sortArray(int[] nums) { buf = new int[nums.length]; mergeSort(nums, 0, nums.length - 1); return nums; }}function sortArray(nums: number[]): number[] { const buf: number[] = new Array(nums.length); const mergeSort = (lo: number, hi: number): void => { if (lo >= hi) return; const mid = lo + ((hi - lo) >> 1); mergeSort(lo, mid); mergeSort(mid + 1, hi); let i = lo, j = mid + 1, k = lo; while (i <= mid && j <= hi) { buf[k++] = nums[i] <= nums[j] ? nums[i++] : nums[j++]; } while (i <= mid) buf[k++] = nums[i++]; while (j <= hi) buf[k++] = nums[j++]; for (let x = lo; x <= hi; x++) nums[x] = buf[x]; }; mergeSort(0, nums.length - 1); return nums;}Editorial#
Merge sort is the safest O(n log n) for adversarial inputs (quicksort can degrade to O(n²) without random pivots). The auxiliary buffer is reused across recursive calls to avoid allocations.
Complexity#
- Time: O(n log n).
- Space: O(n).
Concept revision#
Related#