2013-02-20 2 views
1

Я пытаюсь решить проблему в O (n) времени, когда, учитывая два передних итератора перед контейнером и задней частью контейнера, я хочу удалить все элементы в контейнере, которые не отображаются в наименее < это число> раз. Например, для вектора строк, таких как («john», «hello», «one», «yes», «hello», «one»), и я хотел удалить все элементы, которые появляются менее чем в 2 раза, конечный вектор затем будет содержать только («привет», «один»).Можно ли в общем случае сортировать линейное время?

Я думал, что если бы я мог сортировать в O (n) время, я мог бы выполнить этот результат (в O (n) время), но мне тяжело это делать со строками, ints, chars, или что-либо еще (в общем). Я думаю об этом правильно, или есть более простой способ решить проблему?

+3

Сравнение сортов являются наиболее распространенными, и не может быть сделано в O (N) времени. Однако, если вы знаете подробности о своих данных, некоторые O (1) могут быть сделаны. На самом деле, я бы рекомендовал использовать 'std :: unordered_map' и строки преобразования для подсчета, а не для сортировки данных. –

+1

№ п/п №. № –

+0

OP ничего не говорит о сортировке ... Я удивлен, что никто не привел никаких алгоритмов сортировки без сравнения, которые являются O (n). – thang

ответ

2

Да, вы фактически не сортируете, а удаляете элементы.

1). Храните каждое слово в хешсет. 2). Поиск и добавление, если не в hashset.

+0

Обратите внимание, что hashset называется 'unordered_map' в STL. – nneonneo

+0

Конечно, это еще не будет порядок N, так как hashset является log (N) в пределе. –

+0

@HotLicks: ну, на самом деле, O (N) - предел. Хешсет * обычно * выполняет O (1), амортизированный по всем операциям. – nneonneo

1

Там нет необходимости, чтобы отсортировать

1) занесения std::unordered_map<string,vector<int>> indexOfStrings; - O (N)

2) Для каждого string которого vector size() < 2, удалить элемент - O (число делеций) < = O (N)

indexOfStrings - хранит индекс каждой видимости строки. Это позволяет быстро удалить из вектора без необходимости поиска.

+0

Почему 'vector '? Просто сделайте простой счетчик. – nneonneo

+0

@nneonneo Я фактически хранили индексы для элементов, чтобы упростить удаление. Но счетчик и регенерация вектора - это еще один вариант –

1

Вам не нужно своего рода, вам просто нужно unordered_map:

unordered_map<string, int> counter; 
vector<string> newvec; 
for(string &s : v) { 
    if((++counter[s]) == 2) { 
     newvec.push_back(s); 
    } 
} 

Обратите внимание, что это C++ 11 код. (Спасибо @jogojapan за предложение улучшения кода).

2

Короткий ответ: нет. Сортировка на основе сравнения занимает O(n log n) времени. (Это может быть формально доказано.) Если вы знаете что-то о своем вводе (например, ввод распределяется равномерно случайным образом в пределах известного диапазона), то вы можете использовать известные алгоритмы, такие как сортировка ковша или сортировка радикса в O(n) времени. Вопреки @Mooing Duck, нет такой вещи, как сортировка в O(1) времени (это должно быть очевидно - вы должны посетить каждый элемент хотя бы один раз для любого алгоритма сортировки).

Однако, как отметили несколько других плакатов, ваша проблема не требует алгоритма сортировки ...

+0

+1 (было бы фантастически получить ссылку на формальное доказательство). – jogojapan

+1

@jogojapan Я разместил ссылку на pdf полуформального доказательства здесь: http://stackoverflow.com/questions/14023106/re-ordering-an-array-so-it-is-grouped-by-identical- Элементы/14027086 # 14027086 – thang

+0

Если у вас есть копия «Введение в алгоритмы» (иначе CLRS), прочитайте главу 8.1. Если вам не посчастливилось получить копию, вот pdf, который дает суть: http://www.bowdoin.edu/~ltoma/teaching/cs231/fall07/Lectures/sortLB.pdf – Stephen

Смежные вопросы