C'est une question de devoir. Ils disent que cela prend O(logN + logM)
où N
et M
sont les longueurs des tableaux.
Appelons les tableaux a
et b
. De toute évidence, nous pouvons ignorer tout a[i]
et b[i]
où i> k.
Commençons par comparer a[k/2]
et b[k/2]
. Soit b[k/2]
> a[k/2]
. Par conséquent, nous pouvons également tout rejeter b[i]
, où i> k / 2.
Nous avons maintenant tout a[i]
, où i <k et tout b[i]
, où i <k / 2 pour trouver la réponse.
Quelle est la prochaine étape?
arrays
algorithm
binary-search
Michael
la source
la source
O(logN + logM)
réfère- t-il uniquement au temps nécessaire pour trouver le kième élément? Le prétraitement peut-il être effectué au préalable auprès du syndicat?Réponses:
Vous l'avez, continuez! Et soyez prudent avec les index ...
Pour simplifier un peu, je suppose que N et M sont> k, donc la complexité ici est O (log k), qui est O (log N + log M).
Pseudo-code:
Pour la démonstration, vous pouvez utiliser l'invariant de boucle i + j = k, mais je ne ferai pas tous vos devoirs :)
la source
J'espère que je ne réponds pas à vos devoirs car cela fait plus d'un an que cette question a été posée. Voici une solution récursive de queue qui prendra du temps de log (len (a) + len (b)).
Hypothèse: les entrées sont correctes. c'est-à-dire que k est compris entre [0, len (a) + len (b)]
Cas de base:
Étapes de réduction:
a
+ l'indice moyen deb
est inférieur àk
a
est supérieur à l'élément milieu deb
, nous pouvons ignorer la première moitié deb
, ajustezk
.a
, ajusterk
.k
est inférieur à la somme des indices intermédiaires dea
etb
:a
est supérieur à l'élément milieu deb
, nous pouvons ignorer en toute sécurité la seconde moitié dea
b
Code:
Veuillez noter que ma solution crée de nouvelles copies de tableaux plus petits à chaque appel, cela peut être facilement éliminé en ne passant que les index de début et de fin sur les tableaux d'origine.
la source
kthlargest()
il renvoie(k+1)
-th plus petits éléments, par exemple,1
est le deuxième plus petit élément de0,1,2,3
ie, votre fonction retournesorted(a+b)[k]
.Beaucoup de gens ont répondu à cette question «ke plus petit élément de deux tableaux triés», mais généralement avec seulement des idées générales, pas un code de travail clair ou une analyse des conditions aux limites.
Ici, je voudrais l'élaborer soigneusement avec la façon dont je suis allé pour aider certains novices à comprendre, avec mon code Java fonctionnel.
A1
etA2
sont deux tableaux ascendants triés, avecsize1
etsize2
comme longueur respectivement. Nous devons trouver le k-ème plus petit élément de l'union de ces deux tableaux. Ici, nous supposons raisonnablement cela(k > 0 && k <= size1 + size2)
, ce qui implique celaA1
etA2
ne peut pas être à la fois vide.Tout d'abord, abordons cette question avec un algorithme lent O (k). La méthode consiste à comparer le premier élément des deux tableaux,
A1[0]
etA2[0]
. Prenez le plus petit, ditesA1[0]
-le dans notre poche. Ensuite, comparezA1[1]
avecA2[0]
, et ainsi de suite. Répétez cette action jusqu'à ce que notre poche atteigne lesk
éléments. Très important: dans la première étape, nous ne pouvons nous engager queA1[0]
dans notre poche. Nous ne pouvons PAS inclure ou exclureA2[0]
!!!Le code O (k) suivant vous donne un élément avant la bonne réponse. Ici, je l'utilise pour montrer mon idée et la condition aux limites de l'analyse. J'ai le code correct après celui-ci:
L'idée la plus puissante est que dans chaque boucle, nous utilisons toujours l'approche du cas de base. Après nous être engagés sur le plus petit élément actuel, nous nous rapprochons de la cible: le k-ème plus petit élément. Ne sautez jamais au milieu et soyez confus et perdu!
En observant le cas de base du code ci-dessus
k == 1, k == size1+size2
, et combinez-le avec celaA1
etA2
ne peut pas être les deux vides. Nous pouvons transformer la logique en un style plus concis ci-dessous.Voici un code de travail lent mais correct:
Nous pouvons maintenant essayer un algorithme plus rapide fonctionnant à O (log k). De même, comparez
A1[k/2]
avecA2[k/2]
; siA1[k/2]
est plus petit, alors tous les éléments deA1[0]
àA1[k/2]
devraient être dans notre poche. L'idée est de ne pas simplement s'engager sur un élément dans chaque boucle; la première étape contient desk/2
éléments. Encore une fois, nous ne pouvons PAS inclure ou exclureA2[0]
deA2[k/2]
toute façon. Donc, dans un premier temps, nous ne pouvons pas aller plus loin que desk/2
éléments. Pour la deuxième étape, on ne peut pas aller plus que desk/4
éléments ...Après chaque étape, nous nous rapprochons beaucoup plus du k-ème élément. En même temps, chaque pas devient de plus en plus petit, jusqu'à ce que nous atteignions
(step == 1)
ce qui est(k-1 == index1+index2)
. Ensuite, nous pouvons à nouveau nous référer au cas de base simple et puissant.Voici le code correct de fonctionnement:
Certaines personnes peuvent s'inquiéter si
(index1+index2)
sauter par-dessus k-1? Pouvons-nous manquer le cas de base(k-1 == index1+index2)
? C'est impossible. Vous pouvez additionner 0,5 + 0,25 + 0,125 ..., et vous n'irez jamais au-delà de 1.Bien sûr, il est très facile de transformer le code ci-dessus en algorithme récursif:
J'espère que l'analyse ci-dessus et le code Java pourront vous aider à comprendre. Mais ne copiez jamais mon code comme devoirs! À votre santé ;)
la source
else if (A1[size1 - 1].compareTo(A2[size2 - 1]) < 0)
place deelse if (A1[size1 - 1].compareTo(A2[size2 - 1]) > 0)
? (Dans le code kthSmallestSlowWithFault)Voici une version itérative C ++ de la solution de @ lambdapilgrim (voir l'explication de l'algorithme ici):
Cela fonctionne pour tous les
0 <= n < (size(a) + size(b))
index et estO(log(size(a)) + log(size(b)))
complexe.Exemple
la source
Ma tentative pour les k premiers nombres, le kième nombre dans 2 tableaux triés et dans n tableaux triés:
Le code complet avec les utilitaires de débogage peut être trouvé à: https://github.com/brainclone/teasers/tree/master/kth
la source
Voici mon code basé sur la solution de Jules Olleon:
la source
Voici mon implémentation en C, vous pouvez vous référer aux explications de @Jules Olléon pour l'algorithme: l'idée derrière l'algorithme est que nous maintenons i + j = k, et trouvons ces i et j pour que a [i-1] <b [j-1] <a [i] (ou inversement). Maintenant, puisqu'il y a i éléments dans 'a' plus petits que b [j-1], et j-1 éléments dans 'b' plus petits que b [j-1], b [j-1] est le i + j-1 + 1 = kème plus petit élément. Pour trouver un tel i, j, l'algorithme effectue une recherche dichotomique sur les tableaux.
la source
Voici ma solution. Le code C ++ imprime la kème plus petite valeur ainsi que le nombre d'itérations pour obtenir la kème plus petite valeur en utilisant une boucle, ce qui à mon avis est de l'ordre de log (k). Le code exige cependant que k soit plus petit que la longueur du premier tableau, ce qui est une limitation.
la source
Le premier pseudo code fourni ci-dessus ne fonctionne pas pour de nombreuses valeurs. Par exemple, voici deux tableaux. int [] a = {1, 5, 6, 8, 9, 11, 15, 17, 19}; int [] b = {4, 7, 8, 13, 15, 18, 20, 24, 26};
Cela n'a pas fonctionné pour k = 3 et k = 9. J'ai une autre solution. Il est donné ci-dessous.
Mais ... cela ne fonctionne pas non plus pour k = 5. Il y a cette prise paire / impaire de k qui ne le laisse pas simple.
la source
la source
Voici ma solution en java. Essaiera de l'optimiser davantage
Ceci est inspiré d'Algo à la merveilleuse vidéo youtube
la source
Lien vers la complexité du code (log (n) + log (m))
Lien vers le code (log (n) * log (m))
Implémentation de la solution (log (n) + log (m))
Je voudrais ajouter mon explication au problème. Il s'agit d'un problème classique où nous devons utiliser le fait que les deux tableaux sont triés. on nous a donné deux tableaux triés arr1 de taille sz1 et arr2 de taille sz2
a) Supposons si
Vérifier si k est valide
alors nous ne pouvons pas trouver le kème plus petit élément dans l'union des deux tableaux triés ryt Donc, retournez des données invalides. b) Maintenant, si la condition ci-dessus est fausse et que nous avons une valeur valide et faisable de k,
Gestion des cas Edge
Nous ajouterons les deux tableaux par des valeurs -infinity au début et + des valeurs infinies à la fin pour couvrir les cas de bord de k = 1,2 et k = (sz1 + sz2-1), (sz1 + sz2) etc.
Algorithme principal
Maintenant, nous allons faire une recherche binaire sur arr1. Nous allons faire une recherche binaire sur arr1 à la recherche d'un index i, startIndex <= i <= endIndex
tel que si nous trouvons l'index correspondant j dans arr2 en utilisant la contrainte {(i + j) = k}, alors si
Puisque nous savons que le kème élément le plus petit a (k-1) éléments plus petits que lui en union des deux tableaux ryt? Alors,
Dans le cas 1 , ce que nous avons fait, nous nous sommes assurés qu'il y avait un total de (k-1) éléments plus petits à arr1 [i] parce que les éléments plus petits que arr1 [i] dans le tableau arr1 sont i-1 en nombre que nous savons (arr2 [ j-1] <arr1 [i] <arr2 [j]) et le nombre d'éléments plus petit que arr1 [i] dans arr2 est j-1 car j est trouvé en utilisant (i-1) + (j-1) = (k -1) Donc le kième élément le plus petit sera arr1 [i]
Mais la réponse peut ne pas toujours provenir du premier tableau, c'est-à-dire arr1, donc nous avons vérifié le cas2 qui satisfait également de la même manière que le cas 1 car (i-1) + (j-1) = (k-1). Maintenant, si nous avons (arr1 [i-1] <arr2 [j] <arr1 [i]) nous avons un total de k-1 éléments plus petits que arr2 [j] dans l'union des deux tableaux, donc c'est le kème élément le plus petit.
Dans le cas 3 , pour le former à l'un des cas 1 ou 2, nous devons incrémenter i et j sera trouvé en utilisant la contrainte {(i + j) = k} c'est-à-dire dans la recherche binaire, déplacez-vous vers la partie droite, c'est-à-dire faites startIndex = middleIndex
Dans le cas 4 , pour le former à l'un des cas 1 ou 2, nous devons décrémenter i et j sera trouvé en utilisant la contrainte {(i + j) = k} c'est-à-dire dans la recherche binaire se déplacer vers la partie gauche, c'est-à-dire faire endIndex = middleIndex .
Maintenant, comment décider de startIndex et endIndex au début de la recherche binaire sur arr1 avec startindex = 1 et endIndex = ??. Nous devons décider.
Parce que si k est supérieur à la taille du premier tableau, nous pouvons avoir à faire une recherche binaire sur tout le tableau arr1, sinon nous devons seulement en prendre les k premiers éléments, car les éléments sz1-k ne peuvent jamais contribuer au calcul du kème plus petit.
CODE illustré ci-dessous
Pour Solution de complexité (log (n) * log (m))
J'ai juste manqué d'utiliser l'avantage du fait que pour chaque i, le j peut être trouvé en utilisant la contrainte {(i-1) + (j-1) = (k-1)} Donc, pour chaque ii, on appliquait davantage la recherche binaire sur le deuxième tableau pour trouver j tel que arr2 [j] <= arr1 [i] .Cette solution peut donc être optimisée davantage
la source
Fondamentalement, via cette approche, vous pouvez supprimer k / 2 éléments à chaque étape. Le K changera récursivement de k => k / 2 => k / 4 => ... jusqu'à ce qu'il atteigne 1. Ainsi, la complexité temporelle est O (logk)
À k = 1, nous obtenons le plus bas des deux tableaux.
Le code suivant est en JAVA. Veuillez noter que nous soustrayons 1 (-1) dans le code des indices car l'index du tableau Java commence à 0 et non à 1, par exemple. k = 3 est représenté par l'élément dans le 2ème index d'un tableau.
la source
La complexité du temps est O (log (min (n, m)))
la source
La plupart des réponses que j'ai trouvées ici se concentrent sur les deux tableaux. bien que ce soit bien, mais c'est plus difficile à mettre en œuvre car il y a beaucoup de cas extrêmes dont nous devons nous occuper. En outre, la plupart des implémentations sont récursives, ce qui ajoute la complexité spatiale de la pile de récursivité. Donc, au lieu de me concentrer sur les deux tableaux, j'ai décidé de me concentrer uniquement sur le plus petit tableau et de faire la recherche binaire uniquement sur le plus petit tableau et d'ajuster le pointeur du deuxième tableau en fonction de la valeur du pointeur dans le premier tableau. Par la mise en œuvre suivante, nous avons la complexité
O(log(min(n,m))
avec laO(1)
complexité de l' espace.Nous avons une plage de
[low, high]
tableaux poura
et nous réduisons cette plage au fur et à mesure que nous progressons dans l'algorithme.sizeA
montre combien d'éléments desk
éléments proviennent du tableaua
et dérive de la valeur delow
ethigh
.sizeB
est la même définition sauf que nous calculons la valeur de telle manière quesizeA+sizeB=k
. Le basé sur les valeurs de ces deux bordures concluent que nous devons étendre vers le côté droit dans le tableaua
ou réduire vers le côté gauche. si nous coincés dans la même position , cela signifie que nous avons trouvé la solution et nous retournerons au maximum de valeurs dans la position àsizeA-1
partira
et àsizeB-1
partirb
.la source
Vérifiez ce code.
la source
Sous le code C # pour trouver le k-ième élément le plus petit de l'union de deux tableaux triés. Complexité temporelle: O (logk)
la source
midA
partir deendA
ifk < n
. Vérifiez les tableaux courts, en commençant parreturn B[startB + k - 1];
.)