Ich denke, dass eine Hash-Tabelle eine gute Lösung dafür ist, aber ich stelle mir vor, der Interviewer hat erwartet, dass Sie Ihre eigene Hash-Tabelle erstellen.
Hier ist eine Lösung, die ich in Python entwickelt habe. Ich verwende mod 100
als meine Hash-Funktion und Separate chaining verwenden, um mit Kollisionen umzugehen.
import random
N = random.randint(1, 10**6)
K = 100
HASH_TABLE_SIZE = 100
distinct = [random.randint(1, 10**12) for _ in range(K)]
numbers = [random.choice(distinct) for _ in range(N)]
hash_table = [[] for _ in range(HASH_TABLE_SIZE)]
def hash(n):
hash_key = n % HASH_TABLE_SIZE
bucket = hash_table[hash_key]
for value in bucket:
if value[0] == n:
value[1] += 1
return
bucket.append([n, 1])
for number in numbers:
hash(number)
for bucket in hash_table:
for value in bucket:
print('{}: {}'.format(*value))
EDIT
den Code ein Bit Erklären:
My Hash-Tabelle ist eine 100-Element-Array. Jeder Eintrag im Array ist eine Liste von (number, count)
Einträgen. Um eine Zahl zu hashen, nehme ich den Wert modulo 100, um einen Index in das Array zu finden. Ich scanne die Zahlen, die sich bereits in diesem Bucket befinden, und wenn einer von ihnen mit der aktuellen Nummer übereinstimmt, inkrementiere ich seine Anzahl. Wenn ich die Nummer nicht finden, ich habe einen neuen Eintrag in die Liste mit der Anzahl und einem Anfangszahl von 1.
Optisch anhängen, sieht das Array Art wie folgt aus:
[
[ [0, 3], [34500, 1] ]
[ [101, 1] ],
[],
[ [1502, 1] ],
...
]
Beachten Sie, dass Bei Index n entspricht jeder im Bucket gespeicherte Wert n (mod 100). Im Durchschnitt gibt es nur einen Wert pro Bucket, da es bis zu 100 verschiedene Werte und 100 Elemente im Array gibt.
Um die endgültigen Zählungen auszudrucken, müssen Sie nur durch das Array und jeden Eintrag in jedem Bucket gehen und sie ausdrucken.
EDIT 2
Hier ist eine etwas andere Implementierung, die anstelle Open addressing mit linearer Sondierung verwendet. Ich glaube, ich bevorzuge diesen Ansatz.
hash_table = [None] * HASH_TABLE_SIZE
def hash(n):
hash_key = n % HASH_TABLE_SIZE
while hash_table[hash_key] is not None and hash_table[hash_key][0] != n:
hash_key = (hash_key + 1) % HASH_TABLE_SIZE
if hash_table[hash_key] is None:
hash_table[hash_key] = [n, 1]
else:
hash_table[hash_key][1] += 1
for number in numbers:
hash(number)
for entry in hash_table:
print('{}: {}'.format(*entry))
HINWEIS: Dieser Code wird scheitern wenn es tatsächlich mehr als 100 verschiedene Zahlen sind. (Es wird für immer hängenbleiben und versuchen, einen offenen Punkt im Array zu finden.) Es wäre schön, diesen Zustand zu erkennen (z. B. wenn Sie eine ganze Runde im Array gelaufen sind) und eine Ausnahme auslösen.
Wenn Sie nur theoretische Komplexität interessiert, ist die einfachste für unbegrenzte Anzahl Größe, den Wert in eine Zeichenfolge zu konvertieren, und verwenden Sie das. Für 1 Milliarde passt es in einen 32-Bit-Int, also können Sie das direkt verwenden, mit einem Modulo für die Bin-Platzierung. – Photon
Ein einfacher Vektor (der Größe k) von Paarwert/Anzahl würde den Job erledigen. Die Komplexität des Speichers ist "O (k)", die Komplexität wäre "O (n * k)" (was auf "O (n * log (k))" verringert werden kann ", indem das Array" sortiert "wird. – Jarod42
Ein zufälliger Kommentar, der für Sie relevant sein könnte. Als Interviewer wäre meine erste Frage "Was ist der schlimmste Fall?", Also erwarte ich, dass Sie verstehen, wie Hashtabellen mit Kollisionen umgehen und warum dies nicht die gewünschte O (n) Worst-Case-Leistung liefert. – Charlie