Java 7+, TIO'da n = 50 inç ~ 30 saniye
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;
}
}
}
}
Şimdilik bu zorluğun kod-golf versiyonu için cevabımın yorumlanmamış versiyonu, sadece küçük bir değişiklikle: aralıktaki bir tamsayı java.util.Random#nextInt(limit)
yerine kullanılır , çünkü yaklaşık iki kat daha hızlıdır .(int)(Math.random()*limit)
[0, n)
Çevrimiçi deneyin.
Açıklama:
Kullanılan yaklaşım:
Kod iki bölüme ayrılmıştır:
n
Toplamı rastgele tamsayıların bir listesini oluşturun n squared
.
- Daha sonra tüm değerlerin benzersiz olup olmadığını ve hiçbirinin sıfır olup olmadığını kontrol eder ve her ikisi de falsey ise, bir sonuç elde edene kadar durulayın ve tekrarlayın.
Adım 1 aşağıdaki alt adımlarla yapılır:
1) n-1
Aralıkta rastgele tamsayıların bir miktarını oluşturun [0, n squared)
. Ve eklemek 0
ve n squared
bu listeye. Bu O(n+1)
performansta yapılır .
2) Daha sonra diziyi yerleşik ile sıralar java.util.Arrays.sort(int[])
, Bu, O(n*log(n))
dokümanlarda belirtildiği gibi performansta yapılır :
Belirtilen ints dizisini artan sayısal sıraya göre sıralar. Sıralama algoritması, Jon L. Bentley ve M. Douglas McIlroy'un "Bir Sıralama Fonksiyonu Mühendislik", Software-Practice and Experience, Vol. 23 (11) S. 1249-1265 (Kasım 1993). Bu algoritma, diğer hızlı sıralamaların ikinci dereceden performansa düşmesine neden olan birçok veri kümesinde n * log (n) performansı sunar.
3) Her çift arasındaki farkı hesaplayın. Bu sonuçta ortaya çıkan farklar listesi, n
toplanan tam sayıları içerecektir n squared
. Bu O(n)
performansta yapılır .
İşte bir örnek:
// 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
Bu nedenle yukarıdaki bu üç adım, adım 2'den ve her şeyin etrafındaki döngüden farklı olarak performans için oldukça iyidir, bu temel bir kaba kuvvettir. 2. Adım şu alt adımlara ayrılmıştır:
1) Farklar listesi zaten a java.util.Set
. Bu Setin boyutunun eşit olup olmadığını kontrol edecektir n
. Öyleyse, ürettiğimiz tüm rastgele değerlerin benzersiz olduğu anlamına gelir.
2) Ve aynı zamanda hiçbir içerdiğini kontrol edecektir 0
meydan aralığında rastgele değerler sorar beri Set içinde [1, X]
nerede X
olduğu n squared
eksi toplamı [1, ..., n-1]
da belirttiği gibi, @Skidsdev aşağıda açıklamada.
Yukarıdaki iki seçenekten herhangi biri (tüm değerler benzersiz değilse veya bir sıfır mevcutsa), yeni bir dizi oluşturur ve 1. adıma sıfırlayarak tekrar ayarlayın. Bu, bir sonuç elde edene kadar devam eder. Bu nedenle, zaman biraz değişebilir. TIO için 3 saniyede bir kez n=50
, ama aynı zamanda 55 saniyede bittiğini gördüm n=50
.
Tekdüzelik kanıtlamak:
Bunun tamamen dürüst olduğunu nasıl kanıtlayacağımdan tam olarak emin değilim. java.util.Random#nextInt
Docs tarif edildiği gibi, kesin üniforma:
int
Bu rasgele sayı üretecinin dizisinden eşit olarak dağıtılmış bir sonraki yalancı rayı döndürür . Genel sözleşmesi, nextInt
bir int
değerin sahte olarak üretilip iade edilmesidir. 2 32 olası int
değerin tümü (yaklaşık) eşit olasılıkla üretilir.
Bu (sıralı) rastgele değerler arasındaki farklar elbette tekdüze değildir, ancak bir bütün olarak kümeler tekdüzedir. Yine, bunu matematiksel olarak nasıl kanıtlayacağımdan emin değilim, ancak burada,10,000
n=10
çoğu kümenin benzersiz olduğu bir Sayaçlı bir Haritaya oluşturulan kümeleri (for ) koyacak bir komut dosyası ; bazıları iki kez tekrarlanır; ve tekrarlanan maksimum oluşum genellikle aralıktadır [4,8]
.
Kurulum Talimatları:
Java, Java kodunun nasıl oluşturulacağı ve çalıştırılacağı konusunda bol miktarda bilgiye sahip oldukça iyi bilinen bir dildir, bu kadar kısa tutacağım.
Kodumda kullanılan tüm araçlar Java 7'de mevcuttur (belki de zaten Java 5 veya 6'da, ancak her ihtimale karşı 7'yi kullanalım). Java 7 zaten arşivlenmiş eminim, bu yüzden kodumu çalıştırmak için Java 8 indirmenizi öneririm.
Gelişmelerle ilgili düşünceler:
Sıfır kontrolü için bir iyileştirme bulmak ve tüm değerlerin benzersiz olup olmadığını kontrol etmek istiyorum. 0
Diziye eklediğimiz rastgele değerin zaten içinde olmadığından emin olarak daha önce kontrol edebilirdim , ancak birkaç şey anlamına gelir: dizi ArrayList
yerleşik yöntemi kullanabilmemiz için bir olmalıdır .contains
; henüz listede bulunmayan rastgele bir değer bulana kadar while döngüsü eklenmelidir. Sıfır için kontrol artık .contains(0)
Sette yapıldığı için (sadece bir kez kontrol edilir), performansın .contains
en az n
kez kontrol edilecek olan Listedeki döngüyü eklemeye kıyasla, bu noktada kontrol etmesi daha olasıdır. , ama büyük olasılıkla daha fazla.
Benzersizlik kontrolüne gelince, sadece programın 1. adımından sonra toplanan n
rastgele tamsayılarımız var n squared
, bu yüzden ancak o zaman hepsinin benzersiz olup olmadığını kontrol edebiliriz. Dizi yerine sıralanabilir bir Liste tutmak ve aradaki farkları kontrol etmek mümkün olabilir, ancak ciddiye sadece onları koyarak Set
ve bu Setin boyutu bir n
kez olup olmadığını kontrol daha performans artıracaktır şüpheliyim .