Вы правы, сложность пространства равна O(n*logn)
, но требует некоторого пояснения.
Моя логика в том, что метод сортировки выделяет массив размера n каждый разон вызывается, и он называется общим количеством log (n) раз.
На самом деле, sort
вызывается всего n
раз во время сортировки, но максимальная глубина рекурсииlogn
во время процесса.Давайте нарисуем дерево рекурсивных вызовов:
sort
/ \
sort sort
/\ /\
sort sort sort sort
...
На каждом уровне каждая функция sort
выполняет половину работы своего родителя.Так, на уровне 0 (корневой узел), sort
имеет n
итераций, на уровне 1 каждый из двух сортов имеет n/2
время выполнения (вместе это n
), на уровне 2 каждый из четырех сортов имеет n/4
и т. Д. В совокупности каждый уровень выполняет n
итераций, а поскольку глубина дерева составляет log n
, вы получаете O(n*logn)
сложность времени.
Однако в вашем случае aux
выделяет n
элементов, независимо от текущей глубины, и есть n
вызовов сортировки, так что на первый взгляд можно сделать вывод, что сложность пространства равна O(n*n) = O(n^2)
. Это не , потому что как только мы закончим с каждым рекурсивным вызовом, выделенное пространство освобождается, и существует максимум logn
рекурсивных вызовов.
Обратите внимание, что aux
ненужно выделяет массивn
элементов каждый раз.Вы можете улучшить алгоритм, если объявите aux
в функции merge
и установите соответствующую длину, примерно так:
private static void merge(int[] a, int lo, int mid, int hi) {
int[] aux = new int[hi - lo + 1];
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++)
aux[k - lo] = a[k];
for (int k = lo; k <= hi; k++) {
if (i > mid)
a[k] = aux[j++ - lo];
else if (j > hi)
a[k] = aux[i++ - lo];
else if(aux[j - lo] < aux[i - lo])
a[k] = aux[j++ - lo];
else
a[k] = aux[i++ - lo];
}
}
HTH.