40 votes

Question sur les devoirs

Vous êtes donné un tableau avec des entiers entre 1 et 1 000 000. Un entier est dans le tableau à deux reprises. Comment pouvez-vous déterminer qui? Pouvez-vous penser à un moyen de le faire en utilisant peu de mémoire supplémentaire.

Algo:

  • Solution 1:
    1. Avoir une table de hachage
    2. Itérer tableau et stocker ses éléments dans la table de hachage
    3. Dès que vous trouvez un élément qui est déjà dans la table de hachage, c'est la dup élément
    • Pour:
      • Il s'exécute en O(n) le temps et avec seulement 1 passe
      Inconvénients:
      • Il utilise O(n) de la mémoire supplémentaire

Solution2:
  1. Trier le tableau à l'aide de fusion tri (en O(nlogn) temps)
  2. Analyser à nouveau et si vous voyez un élément deux fois que vous avez obtenu la dup.
  • Pour:
    • il n'utilise pas de mémoire supplémentaire
    Inconvénients:
    • Temps d'exécution est supérieure à O(n)

Pouvez-vous les gars penser à une meilleure solution?

33voto

lavinio Points 12592

La question est un peu ambigu; lorsque la demande est "la une," signifie le retour de la valeur qui est dupliqué, ou la position dans la séquence de la copie de l'un? Dans le premier cas, l'une de ces trois solutions de travail; s'il est le dernier, le premier est le seul qui vous aideront.

Solution #1: assume tableau qui est immuable

Construire une image bitmap; définir le n- ième bit comme vous parcourir le tableau. Si le bit est mis en place, vous avez trouvé un duplicata. Il s'exécute en temps linéaire, et va travailler pour un tableau de taille.

Le bitmap est créée avec autant de bits qu'il y a de valeurs possibles dans le tableau. Comme vous parcourir le tableau, vous pouvez consulter le n- ième bit de la matrice. Si elle est définie, vous avez trouvé votre double. Si elle ne l'est pas, puis il. (Logique pour ce faire peuvent être vus dans le pseudo-code dans cet article de Wikipédia sur les Bits de tableaux ou de l'utilisation du Système.Les Collections.BitArray classe.)

Solution #2: suppose tableau est mutable

Trier le tableau, puis faire une recherche linéaire jusqu'à ce que la valeur actuelle est égale à la valeur précédente. Utilise le moins la mémoire de tous. Les points de Bonus pour la modification de l'algorithme de tri pour détecter les doublons lors d'une opération de comparaison et de résiliation anticipée.

Solution #3: (ce qui suppose que la matrice de longueur = 1,000,001)

  1. La somme de tous les entiers dans le tableau.
  2. De qui, de soustraire la somme des nombres entiers de 1 à 1 000 000 de inclusif.
  3. Ce qui est à gauche sera votre dupliqué valeur.

Ça prend presque pas de mémoire supplémentaire, qui peut être fait en une seule passe, si vous calculez les sommes en même temps.

L'inconvénient est que vous devez faire la totalité de la boucle pour trouver la réponse.

Les avantages sont la simplicité, et une forte probabilité, il sera en fait courir plus vite que les autres solutions.

9voto

rampion Points 38697

En supposant que tous les nombres de 1 à 1 000 000 dans le tableau, la somme de tous les nombres de 1 à 1 000 000 est - (1,000,000)*(1,000,000 + 1)/2 = 500,000 * 1,000,001 = 500,000,500,000.

Donc juste ajouter tous les nombres dans le tableau, soustraire 500,000,500,000, et vous serez à gauche avec le nombre qui s'est produit à deux reprises.

O(n) en temps et O(1) de la mémoire.

Si l'hypothèse n'est pas vrai, vous pouvez essayer d'utiliser un Filtre de Bloom - ils peuvent être stockés beaucoup plus compacte que d'une table de hachage (car ils ne font que stocker fait de la présence), mais ils ne courent le risque de faux positifs. Ce risque peut être limité si, par notre choix de la quantité de mémoire à passer sur le filtre de bloom.

Nous pouvons alors utiliser la floraison filtre pour détecter les doublons potentiels en O(n) en temps et vérifier chaque candidat en O(n) fois.

6voto

hughdbrown Points 15770

Ce code python est une modification de QuickSort:

def findDuplicate(arr):
    orig_len = len(arr)
    if orig_len <= 1:
    	return None
    pivot = arr.pop(0)
    greater = [i for i in arr if i > pivot]
    lesser = [i for i in arr if i < pivot]
    if len(greater) + len(lesser) != orig_len - 1:
    	return pivot
    else:
    	return findDuplicate(lesser) or findDuplicate(greater)

Il trouve un doublon en O(n logn)), je pense. Il utilise de la mémoire supplémentaire sur la pile, mais il peut être réécrit pour utiliser une seule copie des données d'origine, je crois:

def findDuplicate(arr):
    orig_len = len(arr)
    if orig_len <= 1:
    	return None
    pivot = arr.pop(0)
    greater = [arr.pop(i) for i in reversed(range(len(arr))) if arr[i] > pivot]
    lesser = [arr.pop(i) for i in reversed(range(len(arr))) if arr[i] < pivot]
    if len(arr):
    	return pivot
    else:
    	return findDuplicate(lesser) or findDuplicate(greater)

Les interprétations de la liste que produire plus et à moindre détruire l'original avec des appels à la pop(). Si arr n'est pas vide après la suppression de plus et de moins , alors il doit y avoir un doublon et il doit être pivot.

Le code souffre de l'habitude de débordement de pile problèmes sur les données triées, donc, soit de façon aléatoire un pivot ou une solution itérative qui les files d'attente de données est nécessaire:

def findDuplicate(full):
    import copy
    q = [full]
    while len(q):
    	arr = copy.copy(q.pop(0))
    	orig_len = len(arr)
    	if orig_len > 1:
    		pivot = arr.pop(0)
    		greater = [arr.pop(i) for i in reversed(range(len(arr))) if arr[i] > pivot]
    		lesser = [arr.pop(i) for i in reversed(range(len(arr))) if arr[i] < pivot]
    		if len(arr):
    			return pivot
    		else:
    			q.append(greater)
    			q.append(lesser)
    return None

Cependant, maintenant que le code doit prendre une profonde copie des données dans le haut de la boucle, la modification de la mémoire.

Autant pour l'informatique. Les naïfs algorithme clobbers mon code en python, probablement en raison de python algorithme de tri:

def findDuplicate(arr):
    arr = sorted(arr)
    prev = arr.pop(0)
    for element in arr:
    	if element == prev:
    		return prev
    	else:
    		prev = element
    return None

2voto

T . Points 1589

Plutôt que de trier le tableau et en vérifiant ensuite, je vous suggère d'écrire une mise en œuvre d'une comparaison de la fonction de tri qui se ferme dès que la dup est trouvé, ne menant à aucune mémoire supplémentaire requis (selon l'algorithme que vous choisissez, évidemment) et un pire des cas en O(nlogn) temps (encore une fois, en fonction de l'algorithme), plutôt que les meilleures (et les moyen, selon...) cas O(nlogn) de temps.

E. g. Une mise en œuvre de la place de fusion de tri.

http://en.wikipedia.org/wiki/Merge_sort

2voto

Mike Mu Points 609

Astuce: utilisez la propriété A XOR A == 0 et 0 XOR A == A.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X