2012-02-26 3 views
6

Что будет самой сложной для сортировки n строк, имеющих n символов каждый? Будет ли это всего лишь n раз больше. случай O(n log n) или что-то еще ...?Сортировка строк с использованием Merge Sort

+0

Что вы здесь? – uday

+0

Непонятно, что вы просите. –

+0

отредактировал мой вопрос ..... – Abhishek

ответ

3

Как @orangeoctopus, используя стандартный алгоритм ранжирования в коллекции n строки размером n приведут к вычислению O(n^2 * logn).

Однако - обратите внимание, что вы можете сделать это в O(n^2), с изменениями на radix sort.

Самый простой способ сделать это [по-моему] - это

  1. построить trie и заполнить его со всеми строками. Ввод каждая строка O(n) и вы делаете это n раз - всего O(n^2)
  2. сделать DFS на синтаксическом дереве, каждый раз, когда вы столкнетесь знаком для конца для строки - добавьте его в отсортированную коллекцию. Порядок строк, добавленных таким образом, лексикографически, поэтому ваш список будет отсортирован лексикографически, когда вы закончите.

Легко видеть, что вы не можете сделать это лучше тогда O(n^2), так как только чтение данных является O(n^2), таким образом, это решение является оптимальным с точки зрения большой нотации O сложности времени.

+0

Я думаю, вместо того, чтобы говорить «DFS», говорить «предварительный обход» будет более понятным. – CEGRD

+0

Can 'O (n^2)' достигается без использования trie также? – Kshitij

+0

@Kshitij Да, сделайте сортировку радикса в строке, trie - просто предложение - здесь будет работать стандартная сортировка радикса - с использованием символов (или их битового представления) каждой итерации для достижения текущего частичного порядка, пока вы не исчерпаете все биты /персонажи. Это также займет «O (n^2)». – amit

6

Когда вы говорите о нотации O с двумя вещами различной длины, обычно вы хотите использовать разные переменные, например M и N.

Таким образом, если слияние сортировка O(N log N), где N это число строк ... и сравнение двух строк является O(M) где M весы с длиной строки, то вы останетесь с:

O(N log N) * O(M) 

или

O(M N log N) 

, где M длина строки и N это количество строк. Вы хотите использовать разные ярлыки, потому что они не означают одно и то же.

В странном случае, когда средняя длина строки масштабируется с числом строк, как если бы вы имели матрицу, хранящуюся в строках или что-то вроде этого, можно утверждать, что M = N, и тогда вам придется O(N^2 log N)

+0

Не имеете в виду «O (M) где M ...» вместо «O (N) где N ...»? И в то время как в худшем случае производительность, как и требовалось, следует отметить, что средняя производительность случая для сравнения двух строк - это O (1), поскольку она становится геометрически меньшей и менее вероятно, что вам нужно будет посещать каждый дополнительный символ в строках. – xan

+0

Конечно, я имел в виду их отдельно, но я изменил его, чтобы использовать 'M', чтобы быть более ясным. Он просит «худшую сложность», но дает «средний» размер жало ... так что все равно O (N), правильно? –

+0

Да, вопрос немного неясен с его смешением худшего и среднего. Я думаю, что ваш ответ будет более сильным, чтобы охватить оба. – xan

0

Сортировка n элементов с помощью MergeSort требует сравнения O(N LogN). Если время для сравнения двух позиций - O(1), тогда общее время работы будет O(N logN). Однако для сравнения двух строк длины N требуется O(N) времени, поэтому наивная реализация может зависеть от O(N*N logN) времени.

Это кажется расточительным, потому что мы не воспользовались тем фактом, что для сравнения есть только строки N. Мы могли бы как-то препроцитировать строки, чтобы в среднем сравнение занимало меньше времени.

Вот эта идея. Создайте структуру Trie и поместите туда N строк. У trie будет O(N*N) узлов и потребуется O(N*N) времени на сборку. Пройдите дерево и поместите целое «ранжирование» на каждый узел дерева; Если R (N1) < R (N2), то строка, связанная с Node1, предшествует строке, связанной с Node2 в словаре.

Теперь перейдите к Mergesort, выполните сравнения в O(1), просмотрев Trie. Общее время работы будет O(N*N + N*logN) = O(N*N)

Редактировать: Мой ответ очень похож на @amit. Однако я приступаю к объединению, где он продолжает работу с radixsort после этапа построения trie.

+0

Поддерживаете ли вы также привязку указателей к трем узлам, чтобы получить доступ к этим рейтингам во время сортировки слияния? уточните пожалуйста. Кроме того, я думаю, вы также должны включить стоимость проезда. Таким образом, сложность должна быть O (N * N + N * N + N * logN). Если это так, то подход сортировки по методу радикса выглядит лучше, так как это O (N * N + N * N). – CEGRD

+0

@CERGD: нотация Big O касается только асимптотического роста по размеру ввода; он не имеет дело с постоянными факторами, O (2 * N * N + NlogN) = O (N * N). Повторяя вопрос через несколько месяцев, ясно, что ответ Амита проще и быстрее. Тем не менее, я не согласен с вашим аргументом: единственный способ измерить фактическую производительность - использовать хронометр, а не смотреть на постоянные факторы в O-нотации. Есть даже случаи, когда алгоритм с большей функцией O() превосходит другую в практических ситуациях. –