Possible, Question d'Entrevue: Comment Trouver Toutes Chevauchement des Intervalles de
Ce n'est pas une question d'entrevue soi, que je suis tombé sur ceci dans mon projet, mais j'ai pensé qu'il pourrait être un décent intervew question.
Vous disposez de N paires d'intervalles, dire des entiers. Vous êtes nécessaires pour identifier tous les intervalles qui se chevauchent les uns avec les autres en O(N) fois. Par exemple, si vous avez
{1, 3}
{12, 14}
{2, 4}
{13, 15}
{5, 10}
la réponse est {1, 3}, {12, 14}, {2, 4}, {13, 15}. Notez que vous n'avez pas besoin de leur groupe, de sorte que le résultat peut être dans n'importe quel ordre, comme dans l'exemple.
J'ai juste jeté en O(N) le temps parce que le KMP algorithme prend O(N) pour la chaîne de recherche. 😀
Le meilleur, je suis venu avec et ce que je suis en ce moment dans le projet est en O(N^2). Ouais, la force brute est assez triste, mais personne ne se plaint alors je ne vais pas à refactoriser. 😛 Encore, j'étais curieux de savoir si un plus grand esprit a une solution plus élégante.
- Deux choses ne sont pas claires: (1) vous dites "N paires d'intervalles", mais je suis assez sûr que vous avez réellement dire "N intervalles", car si il y a seulement des N paires de tous les chevauchements peuvent être trivialement trouvé en O(N) 😛 en Supposant N = nombre d'intervalles: (2) Il n'est pas possible de faire état de toutes les paires qui se chevauchent en O(N) le temps parce qu'il y a O(N^2) d'entre eux! Otoh, que c'est raisonnable de demander l'O(N) de la taille d'ensemble de tous les intervalles qui se chevauchent d'au moins un autre intervalle. Est-ce que vous me demandez?
- gbenison de réponse (stackoverflow.com/a/9775727/47984) est le seul des 9 actuellement ici qui répond vraiment à la question en O(nlog n). Veuillez envisager de marquer que la réponse correcte.
- C'est drôle, car j'ai eu un entretien avec amazon et ils m'ont posé une question similaire ....
- Pouvez-vous expliquer pourquoi la réponse de marcog n'est pas en O(n lg n)?
- Le problème est surtout que la question est très mal formulée, comme je l'ai écrit dans mon premier commentaire. Interprétée littéralement, il n'a pas de solution, donc answerers ont (raisonnablement), s'est penché pour "similaires" des problèmes. Si nous interprétons marcog de la revendication du "Nous pouvons trouver des intervalles qui se chevauchent avec qui ..." pour signifier l'inscription de toutes les paires de chevauchement des intervalles, ce qui contredit son revendiquer plus tard que "C'est un O(N logN) solution" -- il pourrait y avoir O(n^2) paires, qui n'algorithme de liste en O(n log n) en temps.
- Fondamentalement, marcog de l'algorithme est une bonne façon de répondre à quelques questions en O(n log n) temps (comme le nombre de paires chevauchements il y a), mais il n'essaie pas de préciser qu'il vous arrive quelque chose de moins que cela (l'évidence de l'interprétation de) ce que l'OP réellement demandé. Otoh, que gbenison explicitement essayé de bidouiller les OP de la question en quelque chose de raisonnable (c'est à dire, en fait résoluble en temps O(n log n) en temps), à savoir, "la Liste de tous les intervalles qui se chevauchent d'au moins un autre intervalle" -- et puis le résoudre.
- Je suis d'accord que la formulation n'est pas claire, mais mon interprétation initiale de la question est: Trouvez tous les intervalles qui se chevauchent avec un autre intervalle. Pour le dire plus précisément, trouvez tous les intervalles qui se chevauchent avec au moins un autre intervalle. D'autre part, si la question clairement indiqué "trouver toutes les paires d'intervalles qui se chevauchent les uns avec les autres", alors que ce serait O(N^2) comme vous l'avez dit. Notez que l'opération de l'exemple ne montre pas de paires, mais plutôt individu intervalles.
- Cette interprétation de la question est ce que gbenison première rend explicite, et puis en résout. marcog réponse, otoh, que, néglige de clarifier les choses, puis dit qu'avec un peu d'extra tenue de livres que vous pouvez "trouver les intervalles se recoupent avec qui", ce qui pour moi implique clairement toutes les paires d'intervalles -- et ensuite prétend O(n log n) en temps. Mais la découverte de ces paires nécessite O(n^2).
Vous devez vous connecter pour publier un commentaire.
Jeter les extrémités des intervalles dans un tableau, en les marquant comme de début ou de fin points. Trier par rompre les liens en plaçant les points d'extrémité avant le démarrage de points si les intervalles sont fermées, ou à l'inverse s'ils sont à moitié ouvertes.
Puis itérer sur la liste, garder une trace de combien d'intervalles nous sommes dans (cette valeur correspond au nombre de start-points traités moins nombre de points). Chaque fois que nous avons atteint un point de départ alors que nous sommes déjà dans un intervalle, ce qui signifie que nous devons avoir de chevauchement des intervalles.
Nous pouvons trouver les intervalles se recoupent avec qui en stockant des données à côté de la fin-points, et de garder trace des intervalles de nous sommes.
C'est un O(N logN) de la solution, avec tri être le principal facteur.
{1,2} and {2,3}
ne se chevauchent pas. Si ils sont des intervalles fermés, alors que c'est un chevauchement. La Question ne précise pas laquelle.{1,3},{2,4},{2,7},{6,8}
ainsi, puis de ce droit?Trier les intervalles point de départ. Puis rabattre sur cette liste, la fusion de chaque intervalle avec son voisin (c'est à dire (1,4),(2,6) -> (1,6)) si elles se chevauchent. La liste contient les intervalles sans superposition de partenaire. Filtre à partir de la liste d'origine.
C'est linéaire dans le temps après la première opération de tri qui peut être fait avec n'importe quel (n log n) de l'algorithme. Pas sûr de savoir comment vous obtenez autour de cela. Même le "filtrer les doublons' opération à la fin est linéaire si vous prenez avantage de déjà-de l'ordre de tri de l'entrée et la sortie de la première opération.
Voici une implémentation en Haskell:
overlap
condition peut être simplifié àoverlap (_, b1) (a2,_) | b1 > a2 = True | otherwise = False
, ou tout simplement:overlap (_, b1) (a2,_) = b1 > a2
en supposant que les a1 sont triés. Otherwsie, justeoverlap (_, b1) (a2,_) = (b1>a2) && (a1<a2)
L'approche standard pour les intervales-sur-le-problèmes de ligne est de les trier selon le point de départ et ensuite de simplement à pied de la première à la dernière.
O(n*logn)
(O(n)
si déjà trié)current
intervalle est "déclarée isolé" immédiatement, ne suis-je? Je n'ai même pas dire que c'est une solution. Il y a de nombreuses façons d'adapter l'approche à ce problème particulier, par exempleisolated[current - 1] = false
ou celui que vous avez mentionné.Pas sûr au sujet de O(N) mais que faire si nous avons d'abord les trier par le premier nombre de chaque tuple, et ensuite de façon séquentielle trouver celles dont le premier numéro du tuple est plus grand que le plus grand nombre dans les n-uplets, aussi, qui ne se chevauchent pas avec la prochaine tuple.
De sorte que vous obtenez d'abord:
{1, 3}, {2,4}, {5, 10}, {12, 14}, {13, 15}
depuis le 4 (la plus grande) < 5 et 10 < 12, {5, 10} est isolé.
Cela impliquerait que nous gardons la trace du plus grand nombre que l'on rencontre, et chaque fois que nous trouvons un tuple dont le nombre de départ est plus grand, nous vérifions si elle se confond avec la suivante.
Cela devient dépendante de l'efficacité de l'algorithme de tri puis, parce que le dernier processus serait O(N)
Supposons que la différence entre le départ et les points de terminaison est petit, dire < 32. par exemple. 1..32. Puis chaque intervalle peut être écrite comme une séquence de bits en 32 bits mot. e.g
[1, 2] -> 001; [2, 3]-> 010; [1, 3] -> 011; [2, 3, 4] -> 110
. Deux intervalles, ou des combinaisons d'intervalles, se chevauchent si leur bit à bitAND
est non nul. par exemple.[1,2]
chevauche[1,3]
parce que001&011 == 001
, non nul. O(n) alg est pour garder un bit à bit OU d'intervalles vu jusqu'à présent etAND
chaque nouvelle:Laissée en exercice:
modifier l'algorithme afin d'identifier le chevauchement d'une séquence de bits avec un plus tard, un
travailler sur le motif de bits pour un intervalle de temps en O(1)
Si N paires d'intervalles d'entiers, alors nous pouvons l'obtenir en O(n).
Les trier en premier numéro de la paire, puis le deuxième nombre. Si tous sont des entiers, on peut utiliser seau de tri ou tri radix pour l'obtenir en O(n).
{1, 3}, {2,4}, {5, 10}, {12, 14}, {13, 15}
Puis de combiner un par un,
{1,3}
{1,4} avec chevauchement {1,3} et {2,4}
{1,4}, {5,10}
{1,4}, {5,10}, {12,14}
{1,4}, {5,10}, {12,15} avec chevauchement {12,14} et {13,15}
La combinaison permettrait de prendre en O(N) le temps
Ce problème peut être réduit à l'élément de l'unicité problème.
Élément unicité Omega a(n log n) limite inférieure (comptage du nombre de comparaisons), de sorte que vous ne pouvez pas faire mieux que cela.
Voici un
O(N lg N)
mise en œuvre en Java qui étend la réponse de @Nikita Rybak.Ma solution en trouve chaque intervalle qui chevauche au moins un autre intervalle de compte et à la fois comme le chevauchement des intervalles. Par exemple, les deux intervalles
(1, 3)
et(2, 4)
de l'OP question d'origine se chevauchent les uns les autres, et donc dans ce cas il y a 2 chevauchement des intervalles. En d'autres termes, si Un intervalle de chevauchement avec intervalle de B, puis-je ajouter de A et de B pour l'ensemble des intervalles qui se chevauchent.Maintenant envisager les intervalles de
(1, 100)
,(10, 20)
et(30, 50)
. Mon code constaterez que:Afin de prévenir
(1, 100)
d'être compté deux fois, j'utilise un JavaSet
qui garde seulement unique Intervalle objets.Ma solution suivante de ce plan.
O(N lg N)
.intervalWithLatestEnd
, l'intervalle avec le dernier point de fin.intervalWithLatestEnd
, puis ajouter les deux à un Ensemble. Mise à jourintervalWithLatestEnd
en cas de besoin. Cette étape estO(N)
.Le temps total d'exécution est
O(N lg N)
. Il nécessite un Ensemble de sortie de tailleO(N)
.Mise en œuvre
Afin d'ajouter d'intervalle pour un jeu, j'ai créé un Intervalle personnalisé de classe qui remplacent
equals()
, comme prévu.Et voici le code qui s'exécute l'algorithme:
Cas de Test
Ici est un cas de test qui fonctionne le po d'origine intervalles:
avec le résultat de:
Enfin, voici une version plus avancée du cas de test:
avec le résultat de:
Il a été un certain temps depuis que je l'ai utilisé, mais la solution que j'ai utilisé était un dérivé de la rouge-noir arbre décrit dans l'Introduction aux Algorithmes appelé un intervalle de l'arbre. C'est un arbre triés par intervalle de départ, de sorte que vous pouvez rapidement (binaire de recherche) premier du premier nœud. Autant que je me souvienne, les nœuds ont été commandés par une propriété qui vous permettra d'arrêter de "marcher" dans l'arbre quand les les candidats les nœuds ne peuvent pas correspondre à votre intervalle. Donc je pense que c'est O(m) de recherche, où m est le nombre d'intervalles correspondant.
Je recherche a trouvé cette mise en œuvre.
Brett
[modifier] en Relisant la question, ce n'est pas ce que vous avez demandé. Je pense que c'est la meilleure mise en œuvre lorsque vous avez une liste de (par exemple) de réunions déjà programmées dans les salles de conférence (qui sont ajoutés à l'arbre) et que vous voulez trouver les chambres sont encore disponibles pour une réunion avec un nouveau départ et de la durée (le terme de recherche). Nous espérons que cette solution a une certaine pertinence, mais.
C'est un simple
O(N*log(N))
mise en œuvre en Python:Tout d'abord, il trie les intervalles par la fin du temps, que pour chaque intervalle compare la première fois avec le plus grand temps de mettre fin trouvé, et si elle est plus petite, il signifie qu'il y a un chevauchement.
Le tri de la partie est celui qui nécessite le plus de temps, de sorte que la finale de la complexité est
N*log(N)
.Vous pouvez aller sur la liste une fois et de garder une table de hachage de tous les intervalles rencontré jusqu'à présent. Si une entrée de l'intervalle est une partie d'un certain intervalle de temps à partir de la table de hachage, le fusionner dans la table de hachage de l'intervalle. Marque de la non-primitif intervalles (fusion des intervalles qui se composent de plus d'un intervalle).
Puis vous allez sur la liste un deuxième temps, et pour chaque intervalle de vérifier dans la table de hachage si elle est contenue dans une fusion de l'intervalle ou pas.
Je ne sais pas si c'est O(N), mais c'est beaucoup mieux que O(N^2).