У меня есть набор настраиваемых объектов, которые я добавляю в список, а затем сортирую с помощью настраиваемого компаратора. Затем у меня есть второй список некоторого подмножества этих объектов, которому мне нужен индекс в первом списке, чтобы я мог найти объекты, которые равны (как определено моим компаратором). Поскольку список отсортирован, эти объекты должны быть просто объектами непосредственно перед или после этого объекта, но я заранее не знаю, сколько из них будет одинаковым (вероятно, 2-3).

Мне нужно, чтобы этот поиск выполнялся в постоянное время, так как мой список отсортированных объектов будет довольно большим. Очевидно, я мог бы просто использовать list.index (), но это будет O (N), и я думаю, что смогу сделать лучше. Моя первая мысль заключалась в том, чтобы использовать двусвязный список, но похоже, что мне нужно будет реализовать его самому, и я не совсем уверен, как я буду его отсортировать.

Есть ли в Python реализация двойного связного списка? Или есть лучшая альтернатива этой проблеме? Кроме того, в настоящее время я использую python2.5 и не могу обновить свою версию, но если я ограничен своей версией, мне все равно интересно услышать об этом решении.

0
Fozefy 21 Дек 2016 в 17:34
3
Я думаю, что постоянное время невозможно, если у вас нет другого свойства, которое позволяет вычислять (например, в range). Однако вы всегда можете использовать bisect, если O(log n) достаточно.
 – 
MSeifert
21 Дек 2016 в 17:36
Я думаю, что можно будет получить постоянный поиск по времени, если я сделаю настройку O (N) после сортировки. По крайней мере, я мог бы перебирать список и добавлять индекс объекта к каждому объекту, на который можно было бы ссылаться, когда я вытаскиваю объект из моего второго списка. Это решение кажется чем-то вроде взлома, поскольку я предполагаю, что должен быть способ для реализации списка справиться с этим для меня, но я думаю, что это, скорее всего, сработает.
 – 
Fozefy
21 Дек 2016 в 17:38
2
За дополнительную плату в размере O (N) хранилища вы можете создать словарь для поддержки индексов списка отсортированного списка: dict((e,i) for (i,e) in enumerate(sorted_list)). Это даст вам поиск O (1) для позиции элементов во втором списке.
 – 
wildwilhelm
21 Дек 2016 в 17:42
1
Зависит от того, как элементы реализуют равенство (и что делает настраиваемый компаратор). Помните, что словари обрабатывают ключи как равные тогда и только тогда, когда они равны (obj1 == obj2) и их хэши равны (hash(obj1) == hash(obj2)).
 – 
MSeifert
21 Дек 2016 в 17:45
Я голосую за использование модуля bisect. Невозможно добиться постоянного поиска по времени, исходя из того, что я понимаю из вашей проблемы. Использование двусвязного списка было бы хуже, чем обычного списка (кстати, в стандартной библиотеке есть реализация двусвязного списка: collection.deque).
 – 
Gribouillis
21 Дек 2016 в 17:50

1 ответ

Лучший ответ

По цене дополнительного хранилища O (N) вы можете создать словарь для поддержки индексов списка отсортированного списка:

index_map = dict((e,i) for (i,e) in enumerate(sorted_list))

Это даст вам поиск O (1) для позиции элементов во втором списке.

Если элементы sorted_list являются настраиваемыми объектами, то, как указывает @mseifert, этот подход основан на том, что объекты __eq__ определены правильно, а также являются хешируемыми.

1
wildwilhelm 11 Янв 2017 в 13:50
Обратите внимание, {e: i for i, e in enumerate(sorted_list)} - хороший синтаксический сахар
 – 
hallo
11 Апр 2019 в 06:20
... или, если на то пошло, dict(map(reversed, enumerate(sorted_list))). Не очень сладкий, но может пощекотать людей FP.
 – 
hallo
24 Авг 2019 в 01:13