Trouver un numéro où il apparaît exactement N/2 fois
Ici est l'une de mes questions de l'entrevue. Étant donné un tableau de N éléments et où un élément semble exactement N/2 fois et le reste N/2 éléments sont unique. Comment voulez-vous trouver l'élément avec un meilleur moment de l'exécution?
Rappeler les éléments ne sont pas triés et vous pouvez supposer que N est pair. Par exemple,
input array [] = { 10, 2, 3, 10, 1, 4, 10, 5, 10, 10 }
Voici donc 10 apparaît extactly 5 fois ce qui est N/2.
Je sais une solution à O(n) temps d'exécution. Mais toujours impatient de connaître une meilleure solution en O(log n).
- On m'a dit dans l'interview, il y a une solution avec O(log n) 🙂 ..
- Mais il semble que dans le pire des cas, cela ne pouvait pas être mieux que O(n)
- Pouvez-vous expliquer ce que vous entendez par "un meilleur moment de l'exécution?"?
- 😀 T N de mesurer le nombre d'éléments ou le nombre de bits pour représenter les éléments. Si c'est le dernier, je pense que nous avons notre réponse!
- mieux faire mieux que O(n)
- son absence d'éléments de bien 😉
- Êtes-vous sûr que nous ne savons rien d'autre sur ces éléments? Nous ne savons même s'ils sont des nombres ou pourraient-ils être arbitraire des éléments?
- ils sont des nombres, mais peut être +ve/-ve
- Vous ne savez pas si cela va sembler stupide, mais qu'allons-nous mesurer avec N? accès à des tableaux? les comparaisons entre les deux éléments? puis-je faire des maths sur deux éléments pour le "libre"?
- En gros, nous mesurons combien de fois vous regardez un élément de tableau. Si la taille du tableau de double, votre algorithme de prendre deux fois plus longtemps? Quatre fois plus long? Ou sera le temps seulement d'augmenter un peu? Ou votre algorithme de prendre la même quantité de temps, peu importe comment grand l'entrée est?
- Je sais comment big(0) fonctionne normalement, mais j'ai peur il y a quelques "truc" ou "penser en dehors de la boîte" la réponse à cette question, et je vais essayer de les éradiquer.
- Je ne vois pas comment vous pouvez obtenir O(log n) de ce que si il ya certains de la commande aux éléments.
Vous devez vous connecter pour publier un commentaire.
Il y a une constante de temps de la solution si vous êtes prêt à accepter une faible probabilité d'erreur. Au hasard des échantillons de deux valeurs de l'array, si elles sont les mêmes, vous avez trouvé la valeur que vous recherchez. À chaque étape, vous avez une 0.75 probabilité de ne pas finir. Et parce que pour chaque epsilon, il existe un n tel que (3/4)^n < eps, on peut déguster au plus n fois et retourner une erreur si nous n'avons pas trouvé une paire.
Également remarquer que, si nous continuons d'échantillonnage jusqu'à ce que nous avons trouvé une paire, le temps d'exécution est constante, mais le cas le pire temps d'exécution n'est pas bornée.
Voici ma tentative de preuve que ce ne peut pas être fait en moins de O(n) accès à des tableaux (pour le pire des cas, ce qui est sûrement le seul cas intéressant dans cet exemple):
Supposer le pire des cas log(n) algorithme existe. Cet algorithme accède au tableau au plus log(n) fois. Car il peut faire aucune hypothèse sur les éléments qui sont où, permettez-moi de choisir log(n) éléments qu'il voit. Je vais choisir de lui donner le premier log(n) des éléments uniques. Il n'a pas trouvé le double encore, et il existe encore des n/2 log(n) des éléments uniques pour me nourrir en cas de besoin. En fait, je ne peut pas être forcé à le nourrir un doublon de nombre jusqu'à ce qu'il a lu n/2 éléments. Par conséquent, un tel algorithme ne peut pas exister.
À partir d'un point de vue purement intuitive, cela semble juste impossible. Log(4 milliards de dollars) est de 32. Donc, avec un tableau de 4 milliards de chiffres, de 2 milliards de dollars qui sont uniques, dans aucun ordre particulier, il y a un moyen de trouver la copie de l'élément par la seule vérification de 32 éléments?
M
et N tel que pour toutn >= N
l'algorithme utilise dans la plupartM*log(n)
les opérations de matrice. Maintenant, nous voulonsM*log(N') < N'/2
. Nous pouvons trouver exactement cesN'
pour chaqueM
à l'aide de la fonction log produit, mais nous avons seulement besoin de savoir qu'il existe parce quelogN/N
se développe plus lentement queN
. Ainsi, pour certainsn > N'
nous pouvons prendreM*log(n)
articles sans avoir essayé le nécessaire de la moitié à la suite de votre argument.Je pense que vous avez tout simplement besoin d'analyser à travers le tableau de tenir un carnet de commandes de deux éléments. En tant que N/2 sont à égalité, et le repos est garanti pour être distincts, il doit y avoir un endroit où je dans votre tableau où
a[i] == a[i-1] OR a[i] == a[i-2]
itérer une fois par le biais de votre tableau et vous avez la complexité de près de 2*N, qui doit être bien à l'intérieur de O(N).
Cette réponse est un peu similaire à la réponse par Ganesh M et Dougie, mais je pense un peu plus simple.
Ma Réponse a été,
Runtime - O(N)
Pierre est tout à fait exact. Voici une manière plus formelle de renouvelle sa preuve:
Laisser l'ensemble S est un ensemble contenant N éléments. C'est l'union de deux ensembles: p, qui contient un symbole α répété N/2 fois, et q, qui contient N/2 des symboles uniques ω1..ωn/2. S = p ∪ q.
Supposons qu'il existe un algorithme qui permet de détecter votre dupliqué nombre en log(n) comparaisons dans le pire des cas pour tous les N > 2. Dans le pire des cas, signifie que il n'existe aucune sous-ensemble r ⊂ S tel que |r| = log2 N, où α ∉ r.
Cependant, parce que S = p ∪ q, il y a |p| de nombreux éléments ≠ α dans S. |p| = N/2, donc ∀ N/2 tel que N/2 ≥ log2N, il doit exister au moins un ensemble r ⊂ S tel que |r| = log2N et α ∉ r. C'est le cas pour tout N ≥ 3. Ce qui contredit l'hypothèse ci-dessus, donc il ne peut pas être un tel algorithme.
CQFD.
Faire moins de O(n), vous avez de ne pas lire tous les numéros.
Si vous savez qu'il y est une valeur qui satisifies la relation ensuite, vous pouvez simplement déguster un petit sous-ensemble d'un spectacle qu'un seul numéro apparaît assez de temps pour satisfaire à la relation. Vous devez assumer les valeurs sont raisonnablement réparties uniformément
Modifier. vous devez lire n/2 pour prouver qu'un tel nombre existe, mais si vous en connaissait un certain nombre existé et ne voulait le trouver - vous pu lire sqrt(n) échantillons
La réponse est simple.. et peut être réalisé dans le pire des cas (n/2 + 1) comparaisons
Comparer deux à deux les premier (n-2) numéros, qui est, de comparer nos. à 0 et 1, puis 2 et 3 et ainsi de suite... total n/2 -1 comparaisons.
Si nous trouvons des chiffres identiques dans les comparaisons ci-dessus.. nous avons la répétition de nombre... else:
De prendre l'un des deux derniers numéros restants (disons dernière seconde j'ai pris) et de la comparer avec les chiffres dans la dernière seconde paire.. si le match se produit..deuxième pas durer. est le repated, autrement dernière est la répétition d'un... dans tous les 2 comparaisons.
Total de comparaisons = n/2 - 1 + 2 =n/2 + 1 (pire des cas)
Je ne pense pas qu'il y est tout de O(log n) une méthode pour atteindre cet
Il est assez simple de voir que non O(log n) algorithme existe. Clairement, vous avez à regarder les éléments du tableau de la figure qui est la répétition de l'élément, mais n'importe quel ordre que vous choisissez de regarder les éléments, au premier étage(n/2) les éléments que vous regardez peut-être uniques. Vous pourriez tout simplement être malchanceux. Si cela arrivait, vous n'avez aucun moyen de savoir qui était la répétition de l'élément. Depuis pas d'algorithme qui utilise moins de floor(n/2) références de tableau ou moins sur chaque va fonctionner, il n'y a certainement pas de sous-algorithme linéaire.
Si je suis la compréhension du problème correctement: tout ce que nous savons à propos de la matrice est sa longueur et qu'il a (N/2)+1 éléments uniques, où 1 élément est répété N/2 fois(dans aucun ordre particulier).
Je pense que cette souffre d'une limite physique de O(N) pour la solution que vous ne pouvez pas vraiment affirmer (pour un générique de tableau) que vous avez trouvé le numéro, sans en trouver au moins 2 de ce même numéro. Je ne pense pas qu'il existe une recherche pour un non ordonnée tableau qui peut détecter un duplicata en O(logN) (corrigez-moi si je me trompe). Vous aurez toujours besoin d'en lire au moins N/2 +1 éléments dans le pire des cas.
Retraitement ma solution à partir d'un commentaire de Ganesh version donc je peux le formater:
Probabilité de gagner après 1 itération: 50%
Probabilité de gagner après 2 itérations: 75%
Etc.
Pire des cas, en O(n) en temps O(1) de l'espace.
Noter qu'après N/4 itérations vous avez utilisé toutes les N/2 numéros uniques, de sorte que cette boucle ne sera jamais itérer sur plus des 3/4 de la pile s'il est spécifié.
Supposons que vous avez un python algorithme comme ceci:
L'idée est que arr est votre ensemble de valeurs et de écart est le logarithme en base 2 de la taille. Chaque fois que vous sélectionnez écart éléments et de voir si il y a des doublons. Si oui, de retour de vos coûts (en nombre d'éléments examinés) et le nombre d'itérations (où vous examinez log2(taille) d'éléments par itération). Sinon, regardez un autre écartde la taille d'ensemble.
Le problème avec l'analyse comparative de cet algorithme est que la création des données, chaque passage dans la boucle et l'altération des données est coûteuse, en supposant une grande quantité de données. (Au départ, je faisais 1 000 000 éléments de 10 000 000 d'itérations.)
Donc, nous allons réduire à un équivalent problème. Les données sont transmises en tant que n/2 éléments uniques et n/2 éléments répétés. L'algorithme choisit au hasard des indices de log2(n) des éléments et des contrôles pour les doublons. Maintenant, nous n'avons même pas à créer les données et de supprimer des éléments examinés: il nous suffit de vérifier si nous avons deux ou plusieurs indices sur le point à mi-chemin. Sélectionnez écart index, vérifiez 2 ou plus, le point à mi-chemin: de retour si trouvé, sinon répéter.
Maintenant le code comme ceci:
Si vous essayez ce test, vous verrez que le nombre de fois que l'algorithme a faire des sélections multiples diminue avec le nombre d'éléments de données. C'est, votre coût moyen dans les journaux asymptotiquement approches 1.
Maintenant, est-ce un argument en faveur de l'idéal algorithme étant log2(n) dans la moyenne des cas? Peut-être. Ce n'est certainement pas de même dans le pire des cas.
Aussi, vous n'avez pas à choisir log2(n) éléments à la fois. Vous pouvez choisir 2 et vérifier l'égalité (mais dans le cas dégénéré, vous ne trouverez pas la duplication du tout), ou vérifier qu'un numéro de plus pour la duplication. À ce stade, tous les algorithmes que de sélectionner des éléments et vérifier la duplication à l'identique, ne variant que dans la façon dont beaucoup de qu'ils choisir et comment elles d'identifier les doublons.
Si on vous dit que l'élément que vous recherchez, c'est le non-uniques sûrement le moyen le plus rapide de le faire est d'itérer ainsi que le tableau jusqu'à trouver deux fois la même et puis le retour de cet élément et de cesser de chercher. Au plus vous avez à la recherche de la moitié du tableau.
Je pense que c'est O(n) donc je suppose que cela n'aide pas vraiment.
Il semble trop simple donc je pense que je ne comprends pas le problème correctement.
Ici est Ne Johe réponse en Ruby:
O(n)
Algorithme
RepeatedElement(a, n)
Similaire à https://stackoverflow.com/a/1191881/199556 explication.
Nous allons comparer les 3 éléments(3 opération de comparaison) dans le pire des cas "même" élément n'apparaît qu'une fois.
Nous avons donc réduire la queue par 3 et de réduire le nombre de "même" éléments par un.
À l'étape finale(après k itérations) notre queue contiendra (n/2) - k "même" éléments. Nous allons comparer la longueur de la queue.
D'une part, il n-3k
d'autre part (n/2) - k + 1. Dernière unsame éléments peuvent exister.
n-3k = (n/2) - k + 1
k = 1/4*(n-2)
Après k itérations, nous allons sûrement avoir raison.
Nombre de comparaisons 3/4*(n-2)
Tout d'abord, il est passé de mon lit et je devrais le savoir mieux que de poster le code en public sans essayer d'abord, yada, yada. J'espère que la critique que je vais obtenir au moins d'enseignement. 🙂
Je crois que le problème peut être formulé ainsi: "Trouver le nombre qui se produit plus d'une fois."
Dans l'absolu pire des cas, nous aurions besoin de parcourir un peu plus de la moitié de la liste (1 + N/2) avant nous avons trouvé la 2ème instance d'un nombre non unique.
Pire des cas, exemple: array [] = { 1, 2, 3, 4, 5, 10, 10, 10, 10, 10 }
Sur moyenne cependant, nous ne devons rechercher si 3 ou 4 éléments, puisque la moitié des éléments contiennent les non-numéro unique-je.e à peu près tous les autre numéro.
Parfaitement, même de la distribution des exemples:
En d'autres mots, même si N = 1 millions d'euros, vous n'auraient toujours besoin de la recherche; en moyenne, le premier de 3 ou 4 éléments avant de vous découvert un doublon.
Ce qu'est le big O notation pour un fixe et constante exécution qui n'augmente pas avec N?
Code:
C'est une mauvaise question d'entrevue.
Principalement en raison de la première. Que recherchez-vous? Que le candidat devra venir avec ce O(log n) solution vous ne savez pas existe? Si vous vous posez StackOverflow, est-ce quelque chose que vous pouvez raisonnablement s'attendre à un candidat dans une interview?
Contrairement aux réponses ci-dessus, il existe une solution avec pire des cas comportement comme demandé, O(log n) MOMENT de l'EXÉCUTION.
Le problème n'est pas de trouver une solution avec O(log N) comparaisons pire des cas (ce qui est impossible), mais de le faire en O(log N) temps.
Si vous pouvez le faire N comparaisons en parallèle, la solution est triviale divide-and-conquer.
Pas très pratique dans le monde réel, mais c'est une question d'entrevue, pas un problème réel.
Mise à jour: je pense que vous pouvez le faire en temps constant O(N) processeurs