** (* Ajouté le 13 mai 2020: lorsque le nombre d'éléments de la liste est modifié) **
Chez ABC167 à Atcoder l'autre jour, j'ai viré TLE avec le problème suivant. ・ ABC167D-Teleporter
Téléportez les villes à tour de rôle, arrêtez-vous lorsque la boucle se produit et le nombre de fois restant J'ai réalisé que je devais utiliser mod pour le trouver.
Devenir une boucle ⇔ Rejoindre la même ville ⇔ Déjà dans la liste des villes visitées
J'ai pensé qu'il serait bon de réfléchir, et il a fallu beaucoup de temps pour traiter en utilisant X in list
en Python.
Après tout, j'ai réalisé que je devrais utiliser «X in set» à la place. Je me demandais si la vitesse changerait autant, alors j'ai résumé les résultats de mes recherches.
Extrait de la [documentation officielle] de Python (https://docs.python.org/ja/3/library/stdtypes.html#set-types-set-frozenset)
L'objet set est une collection non ordonnée d'objets hachables uniques. Les utilisations courantes incluent les tests d'attribution, la déduplication des séquences, les ensembles de produits, les ensembles de sommes, les ensembles de différences et les calculs arithmétiques tels que les différences symétriques (sommes logiques exclusives).
Les agrégats, comme les autres collections, prennent en charge x dans l'ensemble, len (ensemble), pour x dans l'ensemble. La collection n'étant pas ordonnée, l'ensemble n'enregistre ni l'ordre d'insertion ni la position des éléments. Par conséquent, l'ensemble ne prend pas en charge l'indexation, le découpage ou tout autre comportement séquentiel.
De plus, les fonctionnalités sont résumées de manière facile à comprendre dans here.
- Le même élément ne contient qu'un seul </ strong>.
En bref, il semble s'agir d'un type de données stocké dans un état trié sans duplication. Pour cette raison, la dichotomie est toujours disponible pour les recherches de type set et semble être plus rapide.
Afin d'étudier le type «liste» et le type «set», j'ai étudié la recherche dans les quatre cas suivants.
nombre | Type de données | Ordre des données | Méthode de recherche |
---|---|---|---|
1 | list |
Aléatoire | Recherche linéaire |
2 | list |
Trié | Recherche linéaire |
3 | list |
Trié | Recherche de bisection |
4 | set |
(Trié) | (Recherche de bisection) |
Pour rendre les autres conditions identiques
Je l'ai fait comme.
main.py
import time
import random
from collections import deque
num = [i+1 for i in range(1000000)]
num_shaffle = random.sample(num, len(num))
num_set = set(num_shaffle)
#Ce qu'il faut chercher
target = [random.randint(1, 1000000) for i in range(10000)]
#type de liste recherche linéaire ou type d'ensemble
def search_seaquence(L):
each_time = deque([])
for i in range(10000):
#écoulé depuis le début_Mesurer le décalage horaire avec le temps
start = time.time()
target[i] in L
elapsed_time = time.time() - start
each_time.append(elapsed_time)
return list(each_time)
#recherche de bissection de type de liste
def search_half(L):
each_time = deque([])
for i in range(10000):
low = 0
high = len(num) - 1
start = time.time()
while low <= high:
mid = int((low + high) // 2)
guess = L[mid]
if guess == target[i]:
break
elif guess > target[i]:
high = mid - 1
else:
low = mid + 1
elapsed_time = time.time() - start
each_time.append(elapsed_time)
return list(each_time)
def cal_time(LIS, mode):
print(mode)
#temps total
sum_time = sum(LIS)
print ("sum_time:{0}".format(sum_time) + "[sec]")
return 0
#Liste aléatoire / recherche linéaire
random_list = search_seaquence(num_shaffle)
cal_time(random_list, 'mode: random list')
#Liste de séquences / recherche linéaire
seaquence_list_seq = search_seaquence(num)
cal_time(seaquence_list_seq, 'mode: seaquence list seaquence')
#Liste de séquences / recherche coupée en deux
seaquence_list_half = search_half(num)
cal_time(seaquence_list_half, 'mode: seaquence list half')
#définir la recherche
set_seek = search_seaquence(num_set)
cal_time(set_seek, 'mode: set')
Méthode de recherche | |||
---|---|---|---|
Liste aléatoire / recherche linéaire | |||
Liste triée / recherche linéaire | |||
Liste triée / dichotomie | |||
définir le type |
D'une manière ou d'une autre, j'essaye d'en faire un graphique.
(** Graphique logarithmique double **.)
Comme prévu, c'est vrai, mais ce n'est pas si différent selon la commande. Je pense que l'ordre de la dichotomie était $ O (\ log n) $, mais c'était assez différent. Il était surprenant que le type «set» soit environ 20 fois plus rapide pour 10 $ ^ 4 $ même dans la même dichotomie. (Peut-être que c'est un problème avec mon code)
Quand j'y ai pensé, j'ai réalisé que l'effet de la commande ne serait pas visible à moins que je ne change le nombre d'éléments dans la destination de recherche (list
/ set
) pour la recherche.
De plus, le nombre d'éléments dans la liste de destination de la recherche est défini sur 10 $ 4, 10 ^ 5, 10 ^ 6 $ tandis que la cible de recherche est fixée sur 10 $ 4 4 $.
J'ai également enquêté sur le moment où il a été changé.
Méthode de recherche\Nombre d'éléments de liste | |||
---|---|---|---|
Liste aléatoire / recherche linéaire | |||
Liste triée / recherche linéaire | |||
Liste triée / dichotomie | |||
définir le type |
(** Graphique logarithmique double **.)
C'est exactement comme commandé. Je suis contente. Il semble que la raison pour laquelle le temps est plutôt réduit dans la recherche de deux minutes est que la destination de la recherche est choisie au hasard. En faisant cela, vous pouvez voir la force de l'ordre des journaux.
Ne pas utiliser «X dans la liste» lors de la recherche de données en double (commande) Après tout, la recherche de deux minutes est rapide
Il peut également être utilisé lors de la recherche de données spécifiques à partir d'une grande quantité de données. Cependant, s'il s'agit d'un type «set», les informations d'index seront perdues. Quand j'ai voulu cette information, j'ai trouvé qu'il était nécessaire de garder la «liste» séparément.
Recommended Posts