Une gamme algorithme d'intersection de mieux que O(n)?
Gamme intersection est un simple, mais non trivial de problème.
Sa a été répondu deux fois déjà:
La première des solutions est de O(n) et la deuxième solution, c'est une base de données (qui est à moins de O(n), bien sûr).
J'ai le même problème, mais pour un grand n et je ne suis pas dans une base de données.
Ce problème semble être très similaire à Magasin 2D des points pour la récupération rapide de ceux à l'intérieur d'un rectangle mais je ne vois pas comment il peut les cartes.
De sorte que la structure de données voulez-vous de stocker l'ensemble des gammes, tels qu'une recherche sur une gamme coûte moins de O(n)? (Crédit supplémentaire pour l'utilisation de bibliothèques disponibles pour Java)
EDIT:
Je veux obtenir un sous-ensemble de l'ensemble d'intersection des plages, sens de la plage de recherche peuvent se croisent plusieurs plages.
La méthode qui doit être inférieure à O(n) en Java:
public class RangeSet {
....
public Set<Range> intersects(Range range);
....
}
Où la Plage est juste une classe contenant une paire de l'int de début et de fin.
Ce n'est pas une question impossible, j'ai déjà la solution, je voulais juste voir si il y avait une plus standard/moyen plus simple de le faire
- Voulez-vous trouver toutes les plages qui se croisent dans une liste? Ou il suffit de cocher une seule gamme pour les intersections avec une liste de plages?
- Et avez-vous réellement besoin d'identifier les intersections, ou tout simplement de les détecter? Si vous avez besoin d'identifier toutes les intersections, vous ne pouvez pas battre O(n), comme toutes les plages dans l'ensemble, pourrait se croisent une requête donnée, dans le pire des cas.
- Comment avez-vous une solution pour ce qui est de moins en moins de O(n) mais peut retourner un ensemble contenant n les plages?
- Je vais le poster dans le bon temps, si il n'y a pas de meilleure façon
- Andrew, avec le droit de structures de données, vous n'avez pas à retourner une plage définie, mais les plages de plages de. E. g. dans mon algorithme ci-dessous lorsque vous suppose que vous avez les plages commandé, vous pouvez obtenir l'index de la première et de la dernière plage qui se chevauchent en O(log n) < O(n) (vous n'avez pas explicite dire à chaque jeu)
- Mais comme vous le dites dans votre réponse, il ne fonctionne que si vous pouvez supposer que vous êtes d'interroger disjoints plages, pas dans le cas général. Je ne suis toujours pas clair à qui la question a été vraiment demander tho.
- Venez pour penser à elle, ma solution n'est pas moins de O(n), soit...donc je ne vais pas le publier.
Vous devez vous connecter pour publier un commentaire.
L'approche standard consiste à utiliser un intervalle d'arbre.
Edit:
Il sonne comme cette solution est plus ou moins un Intervalle d'Arbre. Une information plus complète sur la mise en œuvre d'un Intervalle Arbre peut être trouvé ici.
Prep O(n log n):
De recherche:
Parcourir l'arborescence jusqu'à ce que le pivot > TestRange.Début
2a. Ajouter les feuilles de votre résultat.
Exemple:
Plages:
Arbre:
Non Cumul Des Plages:
Prep O(n log n):
De recherche:
Itérateur de départ à la recherche binaire jusqu'à ce que vous trouver un Start > TestRange.Fin:
2a. Si la plage à la plage de courant est à l'intérieur de la TestRange, l'ajouter à votre résultat.
Cela dépend de votre problème exact, dans la question, les plages de fréquences distinctes, aucune partie commune, et la recherche variait pourrait s'étendre sur plusieurs plages. Si votre problème est le même, il est vraiment facile:
Prendre un tableau de plages, de les trier par leurs valeurs les plus faibles (car ils ne se chevauchent pas, ce serait également le même ordre que triées par leurs valeurs supérieures).
Maintenant il suffit de faire une binsearch pour le votre cible valeur inférieure (ou moins, si elle n'est pas exacte) et un pour la cible valeur supérieure(ou plus si elle n'est pas exacte). Le résultant index sont les plages qui sont couverte. Vous devez vérifier si les plages à l'index lui-même dans - ou exclus, mais qui sont juste 2 chèques. Complexité O(log n).
Intervalles Qui Se Chevauchent:
Prep O(n log n):
Faire un second vecteur d'entiers. Ceci représente le point à partir duquel vous pouvez arrêter de chercher.
De recherche:
Itérateur de départ à la recherche binaire jusqu'à l'arrêt[i] > TestRange.Fin:
2a. Si la plage à la plage de courant est à l'intérieur de la TestRange, l'ajouter à votre résultat.
Si les plages de chevauchement, et que l'on souhaite récupérer tous les plages qui se chevauchent (ou contiennent) une cible de gamme, la plupart des solutions ci-dessus ne semblent pas fonctionner.
Comme certains l'ont souligné, si (dans le pire des cas), tous les plages d'arriver à l'intersection de la fourchette cible (par exemple, si la cible est {0..exemple maxint} ou similaire) alors bien sûr, il prend O(n) pour retourner à la n des plages.
Mais n'est-ce pas la intéressant et typique/moyenne des cas, où seule une très faible % de l'azote total, les plages ne se coupent de la fourchette cible? Appelez le numéro qui ne croisent "m" -- dans ce cas, vous pouvez éventuellement être en mesure de faire aussi bien que O(m). Et si n=10^9 et m=10, c'est un make-or-break différence.
Considérons le cas simple d'un document texte qui a diverses régions marquée pour leur "type", peut-être vous voulez trouver toutes les balisé unités qui en contiennent ou qui se croisent une plage contiguë de texte (par exemple, un paragraphe). En HTML, XML, ou similaires, celles-ci peuvent être les ancêtres du nœud texte(s) contenant au moins certains caractères de la fourchette cible. Dans typique des représentations avec les parents des pointeurs dans chaque nœud, c'est O(m) -- manière de mieux que O(n), en particulier parce que le m est (pour courte ou synchrone des fourchettes cibles) simplement l'arbre d'imbrication, qui tend à être encore plus bas que ln(n) parce que les grands documents XML dans la pratique, obtenir buissonnant pas plus profond.
Le cas intéressant est plus difficile: que faire si votre "éléments" ne forment pas un arbre comme dans le XML, mais peuvent se chevaucher dans les CME, CLIX, LMNL, et quelques autres systèmes? Vous souhaitez trouver toutes les régions/des"éléments" qui se chevauchent de votre cible, mais ils ne sont pas si facilement organisé.
D'autre part, vous devriez être en mesure de le faire très bien balisé des plages dans de nombreuses applications sont le plus souvent les petits, il y a beaucoup plus de mots, des phrases et des paragraphes dans un livre, qu'il y a de chapitres. Donc, même s'il peut y avoir un grand nombre de plages de commencer avant de la cible et un nombre énorme de cette fin d'après elle, l'intersection sera très faible en moyenne.
Je pense que c'est ce que l'original interlocuteur était arriver, et j'ai peur de ne pas voir une réponse qui répond à ce problème. Si ce n'est pas ce à la question d'origine était d'environ, puis j'aimerais vous poser une nouvelle question.
Sonne comme vous avez besoin d'une classe qui implémente l'interface SortedSet. TreeSet est la mise en œuvre qui est livré avec l'API de base.
Ont qu'un seul tenant les plages triées par valeur la plus basse, et un triées par valeur la plus élevée.
Vous pouvez ensuite mettre en œuvre l'équivalent de la base de données de l'algorithme en utilisant les en-jeux de mémoire.
Quant à savoir si c'est effectivement plus rapide que O(n), je ne pouvais pas le dire.
Comme un quad arbre qui fonctionne pour un ensemble de points 2d, un simple arbre binaire devrait fonctionner pour ce cas. Construire un arbre avec vos gammes.
Pour de plus amples explications:
Chaque nœud de l'arbre contient deux entiers, le début et la fin de la gamme, et les deux enfants si ce n'est pas un nœud feuille.
Pour trouver les plages de votre entrée de gamme s'étend, puis à partir du haut de l'arbre
Il devrait être en O(logN)
Plus de détails:
L'arbre binaire serait structuré comme un 1-d version d'un quad, d'arbre en arbre. Chaque nœud aurait trois entiers (désolé je l'ai dit deux ci-dessus, mais maintenant, je réalise que vous avez besoin de trois), la plus basse représente la valeur la plus basse de la plage la plus basse qui est en-dessous de ce nœud, le plus haut représentant la valeur la plus élevée de la gamme la plus élevée qui est en-dessous de ce nœud, et le pivot. La gauche de l'enfant s'est étendue à partir de ce nœud le plus bas de son pivot. Le droit de l'enfant s'est étendue à partir de ce nœud pivot de ce nœud le plus élevé. Si il y a une seule gamme qui va de "la plus faible" à "élevé", vous n'auriez pas un pivot, et ce serait une feuille. Idéalement, vous choisirez les pivots pour chaque nœud de garder l'arbre équilibré.
Quand j'ai eu ce problème, j'ai utilisé un tableau trié de plages et une recherche binaire pour rechercher les intersections. C'est (je crois) O(log n) de la performance, avec un peu de frais généraux à traiter avec des intervalles qui se chevauchent.
La réponse à votre question est, je pense, dérivables à partir du code ci-dessous, mais en arrêtant court de l'insertion. Je vous présente l'ensemble du code pour éviter toute confusion par les différences de contexte - j'ai besoin d'insérer une gamme de Unicode codepoints dans une liste de codepoint plages.
-- EDIT --
Adapter le code ci-dessous pour déterminer les intersections de plusieurs plages implique une simple recherche avant à partir du point d'insertion jusqu'à ce qu'une gamme est constaté, qui n'est plus le croise.
LA FIN DE L'EDIT --
La Gamme classe contient:
Gamme D'Insertion:
Binaires De Recherche: