Java 7+, n = 50 in ~ 30 Sekunden auf TIO
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.Random;
class Main{
public static void main(String[] a){
int n=50;
Random randomGenerator = new Random();
int i = n+1;
int squaredN = n*n;
int[]randomIntegers = new int[i];
randomIntegers[n] = squaredN;
while(true){
for(i=n; i-->1; ){
randomIntegers[i] = randomGenerator.nextInt(squaredN);
}
Set<Integer> result = new HashSet<>();
Arrays.sort(randomIntegers);
for(i=n; i-->0; ){
result.add(randomIntegers[i+1] - randomIntegers[i]);
}
if(!result.contains(0) && result.size()==n){
System.out.println(result);
return;
}
}
}
}
Ungolfed-Version meiner Antwort für die Code-Golf-Version dieser Herausforderung mit nur einer geringfügigen Änderung: Wird java.util.Random#nextInt(limit)
anstelle (int)(Math.random()*limit)
einer Ganzzahl im Bereich verwendet [0, n)
, da sie ungefähr doppelt so schnell ist .
Probieren Sie es online aus.
Erläuterung:
Verwendeter Ansatz:
Der Code ist in zwei Teile unterteilt:
- Generieren Sie eine Liste mit
n
zufälligen Ganzzahlen, die sich summieren n squared
.
- Dann wird geprüft, ob alle Werte eindeutig und keiner Null sind. Wenn einer der beiden Werte falsch ist, wird Schritt 1 erneut versucht, wobei gespült und wiederholt wird, bis ein Ergebnis vorliegt.
Schritt 1 wird mit den folgenden Unterschritten ausgeführt:
1) Generieren Sie ein Array n-1
mit zufälligen Ganzzahlen im Bereich [0, n squared)
. Und füge 0
und n squared
zu dieser Liste hinzu. Dies geschieht in der O(n+1)
Leistung.
2) Dann wird das Array mit dem eingebauten Array sortiert java.util.Arrays.sort(int[])
. Dies erfolgt in der O(n*log(n))
Leistung, wie in den Dokumenten angegeben:
Sortiert das angegebene Ints-Array in aufsteigender numerischer Reihenfolge. Der Sortieralgorithmus ist ein abgestimmter Quicksort, adaptiert von Jon L. Bentley und M. Douglas McIlroys "Engineering a Sort Function", Software-Practice and Experience, Vol. 3, No. 23 (11) S. 1249-1265 (November 1993). Dieser Algorithmus bietet eine n * log (n) -Leistung für viele Datensätze, die dazu führen, dass andere Quicksorts auf eine quadratische Leistung abfallen.
3) Berechnen Sie die Differenz zwischen jedem Paar. Diese resultierende Liste von Unterschieden enthält n
Ganzzahlen, die sich zu summieren n squared
. Dies geschieht in der O(n)
Leistung.
Hier ein Beispiel:
// n = 4, nSquared = 16
// n-1 amount of random integers in the range [0, nSquared):
[11, 2, 5]
// Add 0 and nSquared to it, and sort:
[0, 2, 5, 11, 16]
// Calculate differences:
[2, 3, 6, 5]
// The sum of these differences will always be equal to nSquared
sum([2, 3, 6, 5]) = 16
Diese drei obigen Schritte sind also ziemlich gut für die Leistung, im Gegensatz zu Schritt 2 und der Schleife um das Ganze, die eine grundlegende Brute-Force ist. Schritt 2 ist in folgende Unterschritte unterteilt:
1) Die Differenzliste ist bereits in a gespeichert java.util.Set
. Es wird geprüft, ob die Größe dieses Sets gleich ist n
. Wenn dies der Fall ist, bedeutet dies, dass alle von uns generierten Zufallswerte eindeutig sind.
2) Und es wird auch prüfen, ob es nicht enthält 0
im Set, da die Herausforderung für Zufallswerte im Bereich fragt [1, X]
, wo X
ist n squared
abzüglich der Summe der [1, ..., n-1]
, wie angegeben @Skidsdev unten im Kommentar.
Wenn eine der beiden oben genannten Optionen (nicht alle Werte sind eindeutig oder eine Null vorhanden) vorhanden ist, wird ein neues Array generiert und durch Zurücksetzen auf Schritt 1 erneut festgelegt. Dies wird fortgesetzt, bis ein Ergebnis vorliegt. Aus diesem Grund kann die Zeit sehr unterschiedlich sein. Ich habe gesehen, dass es in 3 Sekunden einmal auf TIO beendet wurde n=50
, aber auch einmal in 55 Sekunden n=50
.
Beweis der Einheitlichkeit:
Ich bin mir nicht ganz sicher, wie ich das beweisen soll, um ganz ehrlich zu sein. Das java.util.Random#nextInt
ist sicher einheitlich, wie in den Dokumenten beschrieben:
Gibt den nächsten pseudozufälligen, gleichmäßig verteilten int
Wert aus der Sequenz dieses Zufallszahlengenerators zurück. Der allgemeine Vertrag von nextInt
ist, dass ein int
Wert pseudozufällig generiert und zurückgegeben wird. Alle 2 32 möglichen int
Werte werden mit (ungefähr) gleicher Wahrscheinlichkeit erzeugt.
Die Unterschiede zwischen diesen (sortierten) Zufallswerten selbst sind natürlich nicht einheitlich, aber die Mengen als Ganzes sind einheitlich. Auch hier bin ich mir nicht sicher, wie ich das mathematisch beweisen soll, aber hier ist ein Skript, das 10,000
generierte Mengen (für n=10
) in eine Karte mit einem Zähler einfügt , wobei die meisten Mengen eindeutig sind. einige wiederholten sich zweimal; und das maximale wiederholte Auftreten liegt gewöhnlich im Bereich [4,8]
.
Installationsanleitung:
Da Java eine ziemlich bekannte Sprache mit vielen verfügbaren Informationen zum Erstellen und Ausführen von Java-Code ist, werde ich mich kurz fassen.
Alle in meinem Code verwendeten Tools sind in Java 7 verfügbar (vielleicht sogar bereits in Java 5 oder 6, aber verwenden wir 7 nur für den Fall). Ich bin mir ziemlich sicher, dass Java 7 bereits archiviert ist, daher würde ich empfehlen, Java 8 herunterzuladen, um meinen Code auszuführen.
Gedanken zu Verbesserungen:
Ich möchte eine Verbesserung für die Prüfung auf Nullen finden und prüfen, ob alle Werte eindeutig sind. Ich könnte 0
vorher ArrayList
nachsehen , indem ich sicherstelle, dass der Zufallswert, den wir dem Array hinzufügen, nicht bereits darin enthalten ist, aber es würde ein paar Dinge bedeuten: Das Array sollte ein sein, damit wir die eingebaute Methode verwenden können .contains
; Eine while-Schleife sollte hinzugefügt werden, bis wir einen zufälligen Wert gefunden haben, der noch nicht in der Liste enthalten ist. Da die Überprüfung auf Null jetzt mit .contains(0)
dem Set durchgeführt wird (das nur einmal überprüft wird), ist es für die Leistung höchstwahrscheinlich besser, sie an diesem Punkt zu überprüfen, als die Schleife mit .contains
in der Liste hinzuzufügen , die mindestens einmal überprüft n
wird , aber höchstwahrscheinlich mehr.
Bei der Eindeutigkeitsprüfung haben wir nur die n
Anzahl der zufälligen Ganzzahlen, die sich n squared
nach Schritt 1 des Programms summieren. Erst dann können wir prüfen, ob alle eindeutig sind oder nicht. Es könnte möglich sein, eine sortierbare Liste anstelle eines Arrays zu führen und die Unterschiede dazwischen zu überprüfen, aber ich bezweifle ernsthaft, dass dies die Leistung verbessern wird, als sie nur in eine Liste zu setzen Set
und zu überprüfen, ob die Größe dieses Sets n
einmal ist.