Comment trouver le k-ième plus petit élément dans l'union de deux tableaux triés?
C'est un des devoirs de la question. Ils disent qu'il faut O(logN + logM)
où N
et M
sont les matrices de longueurs.
Laisser le nom de l'tableaux a
et b
. Évidemment, nous ne pouvons l'ignorer tous les a[i]
et b[i]
où i > k.
D'abord, nous allons comparer a[k/2]
et b[k/2]
. Laissez b[k/2]
> a[k/2]
. Par conséquent, nous ne pouvons ignorer aussi tous les b[i]
, où i > k/2.
Maintenant, nous avons tous a[i]
, où i < k et tous b[i]
, où i < k/2 pour trouver la réponse.
Quelle est la prochaine étape?
Étaient toutes ces étapes comprises dans l'affectation, ou sont les étapes ci-dessus le début de votre algorithme?
Les étapes ci-dessus sont les miennes.
Est
Pas de pré-traitement est prévu.
Sont des doublons admis dans les tableaux?
Les étapes ci-dessus sont les miennes.
Est
O(logN + logM)
seulement référence au temps qu'il faut pour trouver la kième élément? Peut prétraitement être fait pour l'union à l'avance?Pas de pré-traitement est prévu.
Sont des doublons admis dans les tableaux?
OriginalL'auteur Michael | 2011-01-05
Vous devez vous connecter pour publier un commentaire.
Vous l'avez, juste continuer à aller! Et être prudent avec les indices...
Pour simplifier un peu, je vais supposer que N et M sont des > k, de sorte que la complexité 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 vais pas faire tout votre travail 🙂
Comment se fait-O(log k) est O(log n + log m) ?
Cela ne fonctionne pas si toutes les valeurs du tableau 1 sont avant les valeurs dans le tableau 2.
En fait, c'est tout simplement faux. Il ne fonctionne pas du tout.
Pourquoi avez-vous utilisez k/4 comme l'étape la première fois?
OriginalL'auteur Jules Olléon
J'espère que je ne suis pas répondre à vos devoirs comme il l'a été plus d'un an que cette question a été posée. Voici une queue solution récursive qui prendra du log(len(a)+len(b)).
Hypothèse: Les entrées sont à droite. c'est à dire k est dans l'intervalle [0, len(a)+len(b)]
De la Base de cas:
Étapes de réduction:
a
+ mi-indice deb
est à moins dek
a
est supérieure à la mi élément deb
, nous ne pouvons ignorer la première moitié deb
, ajusterk
.a
, ajusterk
.k
est moins que la somme de la mi indices dea
etb
:a
est supérieure à la mi élément deb
, nous pouvons ignorer seconde moitié dea
b
Code:
Veuillez noter que ma solution est la création de nouvelles copies de petits tableaux dans chaque appel, ce qui peut être facilement éliminé par le seul passage de début et de fin des indices sur l'origine des tableaux.
kthlargest()
il retourne(k+1)
-th éléments les plus petits par exemple,1
est le deuxième plus petit élément dans0,1,2,3
c'est à dire, votre fonction retournesorted(a+b)[k]
.j'ai converti votre code C++. Il semble fonctionner
pourriez-vous expliquer pourquoi est-il important de comparer la somme des mi index de a et b avec k?
Dans les étapes de réduction, il est important de se débarrasser d'un certain nombre d'éléments dans un des tableaux proportionnelle à sa longueur afin de faire la course en temps logarithmique. (Ici, nous débarrasser de la moitié). Pour ce faire, nous avons besoin de sélectionner un tableau dont l'une des moitiés nous pouvons ignorer. Comment faisons-nous cela? En toute confiance à l'élimination de la moitié que nous savons pour sûr est pas de la kième élément.
il fonctionne pour moi. Je reçois 10 que la réponse qui est attendue avec 0 en fonction de l'indexation.
OriginalL'auteur lambdapilgrim
De nombreuses personnes ont répondu à cette "k-ième plus petit élément à partir de deux tableau trié" question, mais généralement avec seulement des idées générales, pas une claire code du travail ou des conditions aux limites de l'analyse.
Ici, j'aimerais décrire soigneusement à la façon dont je suis bien d'aider les novices à comprendre, avec mon travail correct de code Java.
A1
etA2
sont deux classés dans l'ordre croissant des tableaux, avecsize1
etsize2
que la longueur, respectivement. Nous avons besoin de trouver la k-ième plus petit élément de l'union de ces deux tableaux. Ici, nous avons des raisons de supposer que(k > 0 && k <= size1 + size2)
, ce qui implique queA1
etA2
ne peut pas être à la fois vide.Tout d'abord, nous allons aborder cette question avec une lente O(k) de l'algorithme. La méthode consiste à comparer le premier élément du tableau,
A1[0]
etA2[0]
. Prendre la plus petite, direA1[0]
loin dans notre poche. Puis comparerA1[1]
avecA2[0]
, et ainsi de suite. Répétez cette action jusqu'à ce que notre poche atteintk
éléments. Très important: Dans la première étape, on ne peut que s'engager àA1[0]
dans notre poche. Nous ne pouvons PAS inclure ou d'exclureA2[0]
!!!La suite de O(k) code vous donne un élément avant la réponse correcte. Ici, je l'utilise pour montrer mon idée, et l'analyse de la condition à la limite. J'ai corriger le code suivant:
Le plus puissant idée est que, dans chaque boucle, nous utilisons toujours le cas de base de l'approche. Après commis à l'actuel plus petit élément, on obtient un pas de plus vers la cible: la k-ième plus petit élément. Ne jamais sauter au milieu et vous rendre confus et perdu!
En observant le code ci-dessus de la base de cas
k == 1, k == size1+size2
, et de les combiner avec quiA1
etA2
ne peut pas à la fois être vide. Nous pouvons inverser la logique en-dessous de façon plus concise style.Ici est lent, mais bon code de travail:
Maintenant, nous pouvons essayer un algorithme plus rapide s'exécute en O(log k). De même, comparer
A1[k/2]
avecA2[k/2]
; siA1[k/2]
est plus petit, alors tous les éléments deA1[0]
àA1[k/2]
devrait être dans la poche. L'idée est de ne pas seulement s'engager à un élément dans chaque boucle, la première étape contientk/2
éléments. Encore une fois, nous ne pouvons PAS inclure ou d'exclureA2[0]
àA2[k/2]
de toute façon. Ainsi, dans la première étape, nous ne pouvons pas aller plusk/2
éléments. Pour la deuxième étape, nous ne pouvons pas aller plusk/4
éléments...Après chaque étape, nous obtenons beaucoup plus proche de k-ième élément. Dans le même temps, chaque étape d'obtenir de plus en plus petites, jusqu'à ce que nous atteignons
(step == 1)
, qui est(k-1 == index1+index2)
. Ensuite, nous pouvons nous référer à la fois simple et puissant de la base de cas à nouveau.Ici est le bon code:
Certaines personnes pourraient s'inquiéter de ce que si
(index1+index2)
sauter par-dessus les k-1? Pourrait nous manquer le cas de base(k-1 == index1+index2)
? C'est impossible. Vous pouvez ajouter jusqu'0.5+0.25+0.125... et vous ne serez jamais aller au-delà de 1.Bien sûr, il est très facile de transformer le code ci-dessus dans l'algorithme récursif:
Espère que l'analyse ci-dessus de code Java et peut vous aider à comprendre. Mais jamais de copier mon code comme vos devoirs! Acclamations 😉
Dans le premier code, ne devrait pas être
else if (A1[size1 - 1].compareTo(A2[size2 - 1]) < 0)
au lieu deelse if (A1[size1 - 1].compareTo(A2[size2 - 1]) > 0)
? (En kthSmallestSlowWithFault code)Merci @Fei. Grande explication. C'est étonnant de voir combien de réponses erronées circulent sur internet concernant ce problème. C'est d'autant plus étonnant que l'on a accepté de répondre à son DONC en ce qui concerne cette question est toujours la bonne. Semble comme personne ne se soucie de tester les réponses.
Peut-être que la coupure de l'O(k) la solution après quelques démarches (15), comme la gamme des mesures de diminution assez rapide.
Dans aucun des appels récursifs les tailles de A1 ou de A2 sont réduits.
OriginalL'auteur Fei
Voici une C++ version itérative de @lambdapilgrim de la solution (voir l'explication de l'algorithme, il n'):
Il fonctionne pour tous les
0 <= n < (size(a) + size(b))
index et aO(log(size(a)) + log(size(b)))
complexité.Exemple
OriginalL'auteur jfs
Une tentative de ma part pour les k premiers nombres, kth numéro 2 triés tableaux, et en n triés tableaux:
Le code complet avec debug utils peut être trouvé à: https://github.com/brainclone/teasers/tree/master/kth
OriginalL'auteur Qichao Dong
Voici mon code sur la base de Jules Olleon la solution:
OriginalL'auteur superb
Voici mon implémentation en C, vous pouvez vous référer à @Jules Olléon s 'explique pour l'algorithme: l'idée de l'algorithme est que nous maintenons i + j = k, et de trouver de telles i et j, de sorte que a[i-1] < b[j-1] < a[i] (ou l'inverse). Maintenant, étant donné qu'il en existe, je les éléments dans 'un' plus petit que b[j-1], et j-1 éléments " b " est plus petit que b[j-1], b[j-1] est le i + j-1 + 1 = k-ième plus petit élément. Pour trouver un tel i,j l'algorithme effectue une recherche dichotomique sur les tableaux.
OriginalL'auteur Zhiwen Fang
Voici ma solution. Le code C++ imprime la k-ième plus petite valeur ainsi que le nombre d'itérations pour obtenir la k-ième plus petite valeur à l'aide d'une boucle, ce qui à mon avis est de l'ordre de log(k). Le code nécessite toutefois un k à être plus petits que la longueur de le premier tableau qui est une limitation.
OriginalL'auteur Karthikeyan Sv
Le premier pseudo code fourni ci-dessus, ne fonctionne pas pour beaucoup de valeurs. Par exemple,
voici deux tableaux.
int[] un = { 1, 5, 6, 8, 9, 11, 15, 17, 19 };
int[] b = { 4, 7, 8, 13, 15, 18, 20, 24, 26 };
Il ne fonctionne pas pour k=3 et k=9. J'ai une autre solution. Il est donné ci-dessous.
Mais... c'est pas non plus de travail pour k=5. Il y a cette pair/impair de capture de k, qui est de ne pas laisser d'être simple.
OriginalL'auteur sn.anurag
OriginalL'auteur Hrishikesh Mishra
Voici la mienne solution en java . Va essayer de continuer à optimiser il
Ce est inspirée de l'Algo à magnifique vidéo sur youtube
OriginalL'auteur M Sach
Lien vers le code complexité (log(n)+log(m))
Lien vers le Code (log(n)*log(m))
Mise en œuvre de (log(n)+log(m)) solution
Je voudrais ajouter mon explication au problème.
C'est un problème classique où il faut utiliser le fait que les deux tableaux sont triés .
nous avons reçu deux tableaux triés arr1 de taille sz1 et arr2 de taille sz2
un)Laisse supposer si
Vérifier Si k est valide
alors nous ne pouvons pas trouver la k-ième plus petit élément dans l'union de deux tableaux triés ryt Donc de retour des données non valides.
b)Maintenant, si la condition est fausse et nous avons valable et réalisable, la valeur de k,
La Gestion Des Cas Limites
Nous allons ajouter deux tableaux par l'infini de valeurs à l'avant et +l'infini de valeurs à la fin pour couvrir le bord de cas de k = 1, 2 et k = (sz1+sz2-1),(sz1+sz2)etc.
Algorithme
Maintenant,nous allons faire une recherche binaire sur arr1 .Nous allons faire une recherche binaire sur arr1 la recherche d'un indice i , startIndex <= i <= endIndex
de telle sorte que si nous trouvons correspondant indice j dans arr2 par la contrainte {(i+j) = k},alors si
Puisque nous savons que la k-ième plus petit élément de a (k-1) éléments plus petits qu'il dans l'union de tous les tableaux ryt? Donc,
Dans Décision1, ce que nous avons fait , nous avons veillé à ce qu'il y a un total de (k-1) éléments les plus petits de arr1[i] parce que les éléments plus petits que arr1[i] dans arr1 tableau i-1, nombre que l'on sait (arr2[j-1] < arr1[i] < arr2[j]) et le nombre d'éléments plus petits que arr1[i] dans arr2 est j-1, parce que j est trouvé en utilisant (i-1)+(j-1) = (k-1) k-ième plus petit élément sera arr1[i]
Mais les réponses ne sont pas toujours du premier tableau ie arr1 donc, nous avons vérifié pour case2 qui satisfait également de la même manière, comme 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 de tous les tableaux de la k-ième plus petit élément.
Dans case3 , pour former à l'un des cas 1 ou le cas 2, nous avons besoin d'incrémenter i et j sera en fonction à l'aide de la contrainte {(i+j) = k} c'est à dire dans la recherche binaire déplacement vers la droite de la partie ie faire startIndex = middleIndex
Dans case4, pour former à l'un des cas 1 ou le cas 2, nous avons besoin de décrémenter i et j sera en fonction à l'aide de la contrainte {(i+j) = k} c'est à dire dans la recherche binaire déplacement vers la gauche de la partie ie faire endIndex = middleIndex.
Maintenant comment décider startIndex et endIndex au début d'une recherche binaire sur arr1
avec startindex = 1 et endIndex = ??.Nous avons besoin de décider.
Parce que si k est plus grand que la taille du premier tableau, nous pourrions avoir à faire une recherche binaire sur l'ensemble de la matrice arr1 d'autre, nous avons seulement besoin de prendre des k premiers éléments de l'parce que sz1-k éléments ne peut jamais contribuer dans le calcul de la k-ième plus petite.
CODE ci-Dessous
Pour la Solution de la complexité (log(n)*log(m))
Juste que j'ai manqué à l'aide de profiter du fait que pour chaque i le j peut être trouvée en utilisant la contrainte {(i-1)+(j-1)=(k-1)} Donc, pour chaque i i a été en outre l'application de la recherche binaire sur le second tableau pour trouver des j tels que arr2[j] <= arr1[i].Si cette solution peut être optimisé en outre
OriginalL'auteur Vinayak Sangar
Fondamentalement, par le biais de cette approche, vous pouvez jeter k/2 éléments à chaque étape.
Le K va changer de manière récursive à partir de k => k/2 => k/4 => ... jusqu'à ce qu'il atteigne 1.
Donc, le Temps de la Complexité est O(logk)
À k=1 , on obtient la plus faible des deux tableaux.
Le code suivant est en JAVA. Veuillez noter que nous sommes en soustrayant 1 (-1) dans le code de l'indices parce que Java du tableau d'index commence à 0 et non pas 1, par exemple. k=3 est représenté par l'élément en 2ème indice d'un tableau.
OriginalL'auteur FaaduBaalak
Temps Complexcity est O(log(min(n,m)))
OriginalL'auteur HeadAndTail
Vérifier ce code.
OriginalL'auteur Anantha Krishnan
Ci-dessous de code C# pour Trouver la k-ième plus Petit Élément dans l'Union de Deux Tableaux Triés. Le temps de la Complexité : O(logk)
il n'y a pas de bug, j'ai testé mon code avant que j'ai posté à DONC
Grâce sammy333, j'ai mis à jour le code. maintenant son travail un
(Ne pas calculer
midA
deendA
sik < n
. Vérifier les tableaux court, en commençant parreturn B[startB + k - 1];
.)OriginalL'auteur Piyush Patel