Временная и пространственная сложность алгоритма «разделяй и властвуй» k-way-merge

Учитывая, что A представляет собой массив из k массивов. Каждый внутренний массив отсортирован и содержит m элементов.

Учитывая этот алгоритм для слияния отсортированных по K массивов, хранящихся в A:

// A is array of sorted arrays  
K-arrays-merge(A)   
1.  if A.length == 1
2.      return first element of A
3.  half = length[A] / 2
4.  firstHalfArray = new array[half][m];
5.  secondHalfArray = new array[half][m];
6.  for (i = 0; i < half; i++)
7.      do firstHalfArray[i] = A[i];
8.  for (i = half; i < length[A]; i++)
9.      do secondHalfArray[i] = A[i];
10. secondHalfArray = Copy second half arrays from A
11. a = K-arrays-merge(firstHalfArray)
12. b = K-arrays-merge(secondHalfArray)
13. return merge(a,b) // This is a merge between two sorted arrays with time complexity of O(n)

Почему временная гибкость этого алгоритма равна O(m*klogk)?

Моя первая мысль заключается в том, что рекурсивный метод запускается logk раз, в каждом раунде копирование массивов выполняется O (m * k), а сортировка слиянием — O (m i log (m i)), где 1 <= i <= logk

Глядя на этапы «разделяй и властвуй»:

  1. Разделить - вычисление средней точки - O (1), копирование массивов - O (mk)
  2. Conquer - 2T(k/2) - Рекурсивные вызовы.
  3. Слияние - сортировка слиянием со сложностью O(m i log (m i)), где 1 <= i <= logk.

Я не знаю, как вычислить временную сложность из этого. Также какова будет пространственная сложность этого алгоритма?


person Community    schedule 15.03.2018    source источник
comment
Название вопроса предназначено для слияния k-way, а не для сортировки слияния k-way. Подход «разделяй и властвуй» подразумевал бы повторные двухсторонние (или некоторое число меньше k) слияний до тех пор, пока не будет создан один объединенный запуск, в отличие от однократного слияния k-ходов. Наибольшая потребность в пространстве возникает при окончательном слиянии для создания одного отсортированного запуска, посмотрите, сможете ли вы выяснить требования для этого.   -  person rcgldr    schedule 15.03.2018


Ответы (1)


Если мы предположим n = mk, временная сложность будет T(k) = 2T(k/2) + n + n. n для копирования массива, n для слияния и 2T(k/2) для рекурсивного вызова. Следовательно, временная сложность алгоритма равна O(nlog k) = O(mk log(k)).

Поскольку каждый раз, когда все значения массива копируются и сохраняются в стеке, а глубина стека равна O(log k), сложность пространства будет O(n log k) = O(mk log k).

person OmG    schedule 15.03.2018
comment
Итак, для достижения решения с mk log k нужно использовать минимальную кучу? Или есть способ, близкий к этому решению с такой временной сложностью? - person ; 15.03.2018
comment
Я допустил ошибку со своей стороны. Все массивы отсортированы, поэтому слияние в последней строке равно O(n). Как это влияет на ответ? - person ; 15.03.2018
comment
можно ли сказать m = O(log k)? Если да, то почему? Если нет, то как найти решение O(mk log k)? - person ; 16.03.2018
comment
@S.Peter Ответ обновлен. У меня ошибка в вычислении n/2. Действительно, у нас 2T(k/2) вместо 2T(n/2). - person OmG; 16.03.2018