Lorsque j'ai deux listes dans OCAML, par exemple
[3; 5; 7]
7 Réponses :
Je ne connais pas OCAML (Syntax-Wise), mais vous pouvez généralement le faire de deux manières: p>
Si votre langue est prise en charge d'un ensemble de données de données de jeu, convertissez les deux listes en ensembles et utilisez l'opération de l'intersection SET. P> LI>
plus généralement: triez les deux listes, puis numérisez les listes de tri, ce qui facilite la recherche des duplicats beaucoup plus efficaces. Vous prenez n journal (n) pour trier et trouver les doublons en temps linéaire. P> li> ol>
OCAML ont défini fonctionnement: Caml.inria.fr/ PUB / DOCS / Manual-OCAML / LIBREF / SET.S.S.HTML Notez que la solution BOT équivalente à terme de complexité (avec OCAML SET).
Comme Franck et Rémi ont dit, convertir vos listes en ensembles (à partir de STDLIB MODULE SET) COÛTS N LOG (N), puis définit une implémentation linéaire de l'intersection. Franck a également mentionné l'alternative équivalente pour trier les listes, puis les traverser de manière synchronisée. Celles-ci sont à peu près les mêmes (et d'ailleurs, dans les deux cas, vous devez être capable de fournir une commande totale sur les éléments de vos listes). P>
Si les intersections sont une partie importante de votre algorithme et que vous souhaitiez qu'ils soient plus rapides dans le cas de deux ensembles d'éléments qui ne sont que légèrement différents, vous devez passer à une structure em> , telle que Patricia arbres. Voir fichiers Si vous avez besoin d'intersection pour être rapide dans tous les cas, vous avez la possibilité d'utiliser des arbres de Patricia comportant un hachage. Le reconscription hachage aide à reconnaître des sous-arbres structurellement identiques et à aider à créer des caches efficaces pour les opérations précédentes en faisant comparaison bon marché. P>
Les arbres Patricia ne peuvent pas utiliser de type arbitraire sous forme de clé (généralement ils sont présentés avec des clés d'INTS). Mais vous pouvez parfois contourner cette limitation en numérotant à la création de chaque valeur que vous souhaitez utiliser comme clé. P> pt * code> dans http: //www.lri .fr / ~ Filliatr / ftp / ocaml / ds / . P>
Mon ocaml n'est pas le meilleur, mais j'ai piraté cette fonction ensemble, qui intersectez les listes triées: qui doit fonctionner dans O (n + m). Fondamentalement, il vérifie le premier élément de chaque liste. S'ils sont égaux, il stocke le résultat de l'appel récursif à leurs queues, puis vérifie si la tête du résultat stocké est égale à la tête des listes. Si ce n'est pas le cas, il l'insère, sinon c'est un duplicata et qu'il l'ignore. P> S'ils ne sont pas égaux, cela avance seulement celui qui est plus petit. P> P>
La fonction me semble bien. J'ai la plus petite des remarques cependant. Si vous écrivez | H3 :: T3 comme L -> H1 :: L code> au lieu de
| H3 :: T3 -> H1 ::( H3 :: T3) Code>, vous pouvez enregistrer le compilateur l'allocation d'une nouvelle cellule de client pour créer une nouvelle liste identique à celle qu'elle a déjà. Le compilateur pourrait faire cette optimisation elle-même, mais ce n'est probablement pas.
Comme @frank suggéré, vous pouvez utiliser des ensembles pour résoudre ce problème, bien que ce ne soit pas la meilleure réponse possible, mais voici une liste de codes courts démontrant comment cela pourrait être atteint dans OCAML:
3 5 7 - : unit = ()
Si vos listes ne contiennent que des entiers d'une taille limitée, il existe également une solution dans O (N): P>
1.) Créez une gamme de booléens de la taille de votre plus grande valeur entière plus 1 dans vos listes d'origine (par exemple dans votre exemple '9 + 1'); Définissez tous les champs sur false; p>
-> 2.) Itérate sur la première liste: pour chaque élément que vous rencontrez, définissez le booléen avec le décalage respectif sur «vrai»; Dans votre exemple, cela céderait p>
-> 3.) Filtrez sur la deuxième liste, conservant uniquement les éléments dont le champ correspondant dans la matrice est vrai p>
-> let m = array.create 10 false code> p>
[| faux; faux; faux; faux; faux; faux; faux; faux; faux; faux |] code> p>
list.iter (amusant x -> m. (x) <- vrai) E1 code> p>
[| faux; faux; faux; vrai; vrai; vrai; vrai; vrai; faux; faux |] code> p>
list.filter (fun x -> m. (x) = true) e2 code> p> p>
[3; 5; 7] code> p>
Je ne pense pas que ma solution est O (n), mais elle est très courte et peut être intéressante pour les personnes qui ne sont pas limitées par des contraintes de complexité (comme cette réponse est l'un des premiers résultats de recherche pour "La liste des intersecteurs OCAML ")
Cette fonction renvoie true quand l'intersection n'est pas vide. En d'autres termes, il vérifie si deux listes d'éléments de partage, si oui, true, sinon faux. P> très similaire, cette fonction renvoie l'intersection réelle. P> < Pré> xxx pré> N'hésitez pas à me corriger si mon Soluton n'est pas correct. Il devrait être polymorphe, car x et y peuvent être n'importe quel type pouvant être comparé. P> P>
En tant qu'affipe précédente a déclaré, il s'agit de l'un des premiers résultats de recherche pour «Intersect listes de OCAML», donc je pose une réponse simple ici qui ne répond pas aux préoccupations concernant la complexité.
# let e1 = [3; 4; 5; 6; 7];; # let e2 = [1; 3; 5; 7; 9];; # List.filter (fun x -> List.mem x e1) e2;; - : int list = [3; 5; 7] #