Détermination du nombre particulier dans le temps et l'espace

10

Étant donné que A[1..n] sont des entiers tels que 0A[k]m pour tous les 1kn , et l'occurrence de chacun nombre sauf un nombre particulier dans A[1..n] est un nombre impair. Essayez de trouver le nombre dont l'occurrence est un nombre pair.

Il existe un algorithme Θ(nlogn) : nous trions A[1..n] en B[1..n] , et B[1..n] en plusieurs morceaux, dont la valeur des éléments est la même, nous pouvons donc compter l'occurrence de chaque élément.

Je veux trouver le pire des cas - O(n) - temps et - O(n) espace.

En supposant que m=Ω(n1+ϵ) et ϵ>0 , le tri radix n'est donc pas acceptable. Les opérations binaires au niveau du bit sont acceptables, par exemple, A[1]xorA[2] .

Yai0Phah
la source
La réponse d'Aryabhata ci-dessous montre que le cas général n'est pas bon, mais peut-être avez-vous d'autres restrictions disponibles? Une restriction simple (mais importante) serait d'imposer que toutes les entrées du tableau sont de taille O(n) . Cela donnerait un algorithme linéaire assez trivial.
Luke Mathieson
1
@LukeMathieson: J'ai supprimé cette réponse, car je ne suis pas encore convaincu que le document que j'ai cité fonctionnera sans aucune modification, et d'ailleurs, OP ne semble s'intéresser qu'au modèle de RAM à coût uniforme.
Aryabhata
@Aryabhata: hehe, eh bien la réponse n'est pas là alors! Par intérêt, et peut-être utile pour Frank, quel a été selon vous le problème avec l'adaptation du résultat dans le document? Un rapide survol suggéra qu'il s'appliquait, mais je ne l'ai évidemment pas lu.
Luke Mathieson
@LukeMathieson: Le fait que les autres éléments doivent apparaître un nombre impair de fois dans le problème actuel. Depuis, j'ai aussi survolé la preuve ...
Aryabhata
Ce serait intéressant si vous vous intéressez aux résultats théoriques ou aux solutions pratiques. Du point de vue théorique, ma première réponse rapide est que vous pouvez trier une liste d'entiers plus rapidement que . Il existe un algorithme déterministe de Han qui s'exécute en temps . Pour les algorithmes randomisés, des résultats encore meilleurs sont connus, par exemple Han et Thorup ont trouvé un algorithme de temps attendu . Cependant, je pense que votre problème ne devrait pas nécessiter de tri. O ( log log n ) O ( n O(nlogn)O(loglogn)O(nloglogn)
A.Schulz

Réponses:

2

Voici une idée pour un algorithme simple; comptez toutes les occurrences!

  1. Trouvez . - heureΘ ( n )m=maxAΘ(n)
  2. "Allouer" . - temps ¹O ( 1 )C[0..m]O(1)
  3. Itérer sur et augmenter de un chaque fois que vous trouvez . Si était , ajoutez à une liste linéaire . - heureC [ x ] A [ _ ] = x C [ x ] 0 x L Θ ( n )AC[x]A[_]=xC[x]0xLΘ(n)
  4. Itérer sur et trouver l'élément avec pair. - temps .x e C [ x e ] O ( n )LxeC[xe]O(n)
  5. Retourne .xe

Dans l'ensemble, cela vous donne un algorithme à temps linéaire qui peut utiliser (dans le sens d'allouer) beaucoup de mémoire. Notez que pouvoir accéder de façon aléatoire à en temps constant indépendamment de est crucial ici.mCm

Un supplémentaire lié à l'espace est plus difficile avec cette approche; Je ne connais aucune structure de données de dictionnaire qui offre une recherche de temps . Vous pouvez utiliser des tables de hachage pour lesquelles voici des implémentations avec temps de recherche attendu ( la taille de la table, le nombre d'éléments stockés) afin que vous puissiez obtenir arbitrairement bien avec un espace linéaire - dans l'attente. Si toutes les valeurs dans correspondent à la même valeur de hachage, vous êtes foutu.O ( 1 ) O ( 1 + k / n ) n k AO(n)O(1)O(1+k/n) nkA


  1. Sur une RAM, cela se fait implicitement; tout ce dont nous avons besoin est la position de départ et peut-être la position de fin.
Raphael
la source
0

Une solution presque triviale - qui utilise cependant l' espace - consiste à utiliser une carte de hachage. Rappelons qu'une carte de hachage a amorti le temps d'exécution pour ajouter et rechercher des éléments.O ( 1 )Θ(n)O(1)

Par conséquent, nous pouvons utiliser l'algorithme suivant:

  1. Attribuer une carte de hachage . Itérer sur . Pour chaque élément , augmentez le nombre d'occurrences vues, ie .A i A H ( i ) + +HAiAH(i)++

  2. Parcourez l'ensemble de clés de la carte de hachage et vérifiez laquelle des clés a un nombre pair d'occurrences.

Maintenant, c'est un algorithme simple qui n'utilise pas vraiment de gros truc, mais parfois même cela suffit. Sinon, vous voudrez peut-être spécifier les restrictions d'espace que vous imposez.

HdM
la source
J'aimerais tout de même savoir s'il existe un algorithme de temps non randomisé utilisant l'espace polynomial. En particulier, existe-t-il des preuves théoriques selon lesquelles il est plus difficile de trouver le seul élément à occurrence paire que de trouver le seul élément à occurrence impaire? O(n)
A.Schulz
@ A.Schulz Je pense que c'est l' algorithme -expected-time en utilisant une table de hachage. Je me souviens que quelqu'un m'a dit un algorithme (ou pour un cas spécial, par exemple, impair = 1 et pair = 2) peut-être avec pile, mais je ne m'en souviens pas. O ( n )O(n)O(n)
Yai0Phah
Toutes les implémentations de table de hachage n'ont pas cette propriété; généralement, la recherche n'est pas , ni même amortie (afaik). En fait, une discussion préalable n'a donné lieu à aucune implémentation avec recherche de temps constante. Peux-tu être plus précis? O(1)
Raphael