2013-02-28 2 views
1

Недавно меня попросили написать код, чтобы найти наивысшие n элементов в списке и вернуть как значения, так и местоположения.Найдите наивысшие n элементов в списке и их местоположениях. Python

Вы можете получить более быстрый (с точки зрения времени выполнения), чем этот?

def highest(L, n): 
    return sorted(enumerate(L), reverse=True, key=lambda x: x[1])[:n] 

if __name__ == '__main__': 

    M = [102, 56, 2355, 3, 25, 78, 19, 25, 1002, -54, 0, 23, -1] 
    r = highest(M,5) 
    print r #[(2, 2355), (8, 1002), (0, 102), (5, 78), (1, 56)] 
+1

Quicker? Или короче? В любом случае, похоже, у вас нет реального вопроса. –

+0

Быстрее с точки зрения времени выполнения, длина кода не важна, если только она не влияет на скорость. –

ответ

9

Если n мал по сравнению с длиной списка, heapq.nlargest должен быть быстрее, чем сортировка всего списка. Это также более читаемо.

def highest(L, n): 
    return heapq.nlargest(n, enumerate(L), key=operator.itemgetter(1)) 

>>> M = [102, 56, 2355, 3, 25, 78, 19, 25, 1002, -54, 0, 23, -1] 
>>> highest(M,5) 
[(2, 2355), (8, 1002), (0, 102), (5, 78), (1, 56)] 

Это будет работать в O (N + NlogN), где N является длина списка и n является количество элементов для возврата, в отличие от O (NlogN) для сортировки.

+0

Я бы добавил, что создание кучи выполняется в линейном времени, а извлечение самого большого элемента выполняется в постоянное время. Таким образом, это действительно асимптотически быстрее, чем O (N log N) сортировки из вопроса. – EOL

+0

@EOL: Извлечение (и удаление) самого большого элемента на самом деле логарифмическое. Я добавил информацию о сложности в ответ. – interjay

+0

Извините, я имел в виду * поиск *, «извлечение», не удаление ... Согласно http://en.wikipedia.org/wiki/Heap_(data_structure)#Comparison_of_theoretic_bounds_for_variants, это действительно делается в постоянном (не логарифмическом) времени, если я правильно понимаю. Теперь 'heapq.nlargest()' действительно может удалить самые большие элементы для выполнения своей работы ... – EOL

1

Просто добавьте, вы можете использовать kth_smallest в pandas, чтобы найти значение в O (N).

import numpy as np 
import pandas as pd 
a = np.array([102, 56, 2355, 3, 25, 78, 19, 25, 1002, -54, 0, 23, -1.0]) 
pd.algos.kth_smallest(a, len(a)-5) 

код здесь:

https://github.com/pydata/pandas/blob/master/pandas/algos.pyx#L653

Примечание: kth_smallest возвращает только значение, но вы можете сканировать массив, чтобы найти место.

+0

Спасибо @HYRY, что приятно знать. Я что-то пропустил, но это наименьшее право, а не самое большое? –

+0

kth_smallest и kth_largest - это тот же алгоритм. – HYRY

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