Tworzę szybką metodę generowania listy liczb pierwszych w zakresie (0, limit + 1). W funkcji kończę usuwanie wszystkich liczb całkowitych z listy wymienionej z listy o nazwie prime. Szukam szybkiego i pythonic sposób usuwania liczb całkowitych, wiedząc, że obie listy są zawsze sortowane.Jaki jest szybki i pythonic/czysty sposób usuwania posortowanej listy z innej posortowanej listy w pythonie?
Mogę się mylić, ale uważam, że list.remove (n) iteruje na liście porównując każdy element za pomocą n. co oznacza, że poniższy kod działa w czasie O (n^2).
# removable and primes are both sorted lists of integers
for composite in removable:
primes.remove(composite)
Opierając się moje przypuszczenie (co może być nie tak i proszę o potwierdzenie, czy jest to poprawne) oraz fakt, że obie listy są zawsze sortowane, to myślę, że poniższy kod działa szybciej, ponieważ tylko pętle na liście raz dla czasu O (n). Jednak nie jest to wcale pythonic lub czyste.
i = 0
j = 0
while i < len(primes) and j < len(removable):
if primes[i] == removable[j]:
primes = primes[:i] + primes[i+1:]
j += 1
else:
i += 1
Czy jest być może wbudowana funkcja lub prostszy sposób robienia tego? A jaki jest najszybszy sposób?
Noty boczne: Nie zmieniłem ustawień funkcji ani kodu powyżej. Nie ma również znaczenia, czy wymieniona lista jest zmieniana/niszczona w procesie.
Dla wszystkich zainteresowanych pełne funkcje jest poniżej:
import math
# returns a list of primes in range(0, limit+1)
def fastPrimeList(limit):
if limit < 2:
return list()
sqrtLimit = int(math.ceil(math.sqrt(limit)))
primes = [2] + range(3, limit+1, 2)
index = 1
while primes[index] <= sqrtLimit:
removable = list()
index2 = index
while primes[index] * primes[index2] <= limit:
composite = primes[index] * primes[index2]
removable.append(composite)
index2 += 1
for composite in removable:
primes.remove(composite)
index += 1
return primes
Jedno wywołanie '' primes.remove' działa w czasie O (n) 'czas , więc twoje czyste drugie rozwiązanie działa również w czasie 'O (n^2)', nie szybszym niż pierwszy. Można to zrobić w czasie 'O (n)', podobnie jak w drugim rozwiązaniu, przez jednoczesne iterowanie na obu listach (ze zmiennymi pętli 'i' i' j', zwiększając tylko jeden z nich na raz), ale budowanie osobna lista wyjściowa. – pts
Przepraszam, chciałem zmienić primes.remove() na liczby pierwsze = liczby pierwsze [: i] + liczby pierwsze [i + 1:] – DavidC
Spójrz na [rozwiązanie Roberta Williama Hanka] (http://stackoverflow.com/a/3035188/190597). Używa listy logicznej i ustawia elementy na False, gdy zostanie ustalone, że (w przybliżeniu) indeks tego elementu nie jest liczbą pierwszą. – unutbu