Java 7+, n = 50 dalam ~ 30 dtk di 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;
}
}
}
}
Versi jawaban saya yang tidak digabungkan untuk versi kode-golf dari tantangan ini untuk saat ini, dengan hanya satu perubahan kecil: java.util.Random#nextInt(limit)
digunakan sebagai ganti(int)(Math.random()*limit)
untuk bilangan bulat dalam kisaran [0, n)
, karena ini sekitar dua kali lebih cepat .
Cobalah online.
Penjelasan:
Pendekatan yang digunakan:
Kode ini dibagi menjadi dua bagian:
- Buat daftar
n
jumlah bilangan bulat acak yang dijumlahkan n squared
.
- Kemudian ia memeriksa apakah semua nilai unik dan tidak ada yang nol, dan jika salah adalah falsey, ia akan mencoba langkah 1 lagi, membilas dan mengulangi sampai kita mendapatkan hasil.
Langkah 1 dilakukan dengan sub-langkah berikut:
1) Hasilkan array n-1
jumlah integer acak dalam rentang [0, n squared)
. Dan tambahkan 0
dan n squared
ke daftar ini. Ini dilakukan dalam O(n+1)
kinerja.
2) Kemudian akan mengurutkan array dengan builtin java.util.Arrays.sort(int[])
, ini dilakukan dalam O(n*log(n))
kinerja, seperti yang dinyatakan dalam dokumen:
Mengurutkan array int tertentu ke dalam urutan numerik. Algoritma pengurutan adalah quicksort yang disetel, diadaptasi dari Jon L. Bentley dan M. Douglas McIlroy "Engineering a Sort Function", Praktek-Perangkat Lunak dan Pengalaman, Vol. 23 (11) P. 1249-1265 (November 1993). Algoritma ini menawarkan kinerja n * log (n) pada banyak set data yang menyebabkan quicksort lain menurun ke kinerja kuadratik.
3) Hitung perbedaan antara masing-masing pasangan. Daftar perbedaan yang dihasilkan ini akan berisi n
bilangan bulat yang dijumlahkan n squared
. Ini dilakukan diO(n)
kinerja.
Berikut sebuah contoh:
// 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
Jadi tiga langkah di atas cukup baik untuk kinerja, tidak seperti langkah 2 dan lingkaran di sekitar semuanya, yang merupakan kekuatan kasar dasar. Langkah 2 dibagi dalam sub-langkah ini:
1) Daftar perbedaan sudah disimpan dalam a java.util.Set
. Ini akan memeriksa apakah ukuran Set ini sama dengan n
. Jika ya, itu berarti semua nilai acak yang kami hasilkan adalah unik.
2) Dan itu juga akan memeriksa bahwa itu tidak mengandung 0
dalam Set, karena tantangan meminta nilai acak dalam kisaran [1, X]
, di mana X
adalah n squared
dikurangi jumlah [1, ..., n-1]
, seperti yang dinyatakan oleh @Skidsdev dalam komentar di bawah ini.
Jika salah satu dari dua opsi di atas (tidak semua nilai unik, atau nol ada), itu akan menghasilkan array baru dan Atur lagi dengan mengatur ulang ke langkah 1. Ini berlanjut sampai kita mendapatkan hasil. Karena itu, waktunya dapat sedikit berbeda. Saya telah melihatnya selesai dalam 3 detik sekali pada TIO untuk n=50
, tetapi juga dalam 55 detik sekali untuk n=50
.
Buktikan keseragaman:
Saya tidak sepenuhnya yakin bagaimana membuktikan ini sepenuhnya jujur. Yang pasti java.util.Random#nextInt
seragam, seperti yang dijelaskan dalam dokumen:
Mengembalikan pseudorandom berikutnya, int
nilai terdistribusi seragam dari urutan generator nomor acak ini. Kontrak umum nextInt
adalah bahwa satu int
nilai dihasilkan dan dikembalikan secara acak. Semua 2 32int
nilai yang mungkin dihasilkan dengan (kurang lebih) probabilitas yang sama.
Perbedaan antara nilai-nilai acak ini (diurutkan) sendiri tentu saja tidak seragam, tetapi set secara keseluruhan seragam. Sekali lagi, saya tidak yakin bagaimana membuktikan ini secara matematis, tetapi di sini ada skrip yang akan meletakkan 10,000
set yang dihasilkan (untuk n=10
) di Peta dengan penghitung , di mana sebagian besar set unik; beberapa diulang dua kali; dan kejadian berulang maksimum biasanya dalam kisaran [4,8]
.
Instruksi instalasi:
Karena Java adalah bahasa yang cukup terkenal dengan banyak informasi yang tersedia tentang cara membuat dan menjalankan kode Java, saya akan membuat ini singkat.
Semua alat yang digunakan dalam kode saya tersedia di Java 7 (mungkin bahkan sudah ada di Java 5 atau 6, tapi mari kita gunakan 7 untuk berjaga-jaga). Saya cukup yakin Java 7 sudah diarsipkan, jadi saya sarankan mengunduh Java 8 untuk menjalankan kode saya.
Pikiran tentang perbaikan:
Saya ingin mencari peningkatan untuk memeriksa nol dan memeriksa semua nilai unik. Saya dapat memeriksa 0
sebelumnya, dengan memastikan nilai acak yang kita tambahkan ke array belum ada di dalamnya, tetapi itu akan berarti beberapa hal: array harus ArrayList
jadi kita dapat menggunakan metode builtin .contains
; loop sementara harus ditambahkan hingga kami menemukan nilai acak yang belum ada dalam Daftar. Karena memeriksa nol sekarang dilakukan .contains(0)
pada Set (yang hanya diperiksa sekali), kemungkinan besar lebih baik untuk memeriksanya pada saat itu, dibandingkan dengan menambahkan loop dengan .contains
pada Daftar, yang akan diperiksa setidaknya n
kali , tetapi kemungkinan besar lebih.
Adapun pemeriksaan keunikan, kami hanya memiliki n
jumlah bilangan bulat acak kami yang berjumlah n squared
setelah langkah 1 program, jadi hanya dengan demikian kami dapat memeriksa apakah semuanya unik atau tidak. Dimungkinkan untuk menyimpan Daftar yang dapat diurutkan alih-alih array, dan memeriksa perbedaan di antara keduanya, tetapi saya benar-benar ragu itu akan meningkatkan kinerja daripada hanya memasukkannya ke dalam Set
dan memeriksa apakah ukuran Set itu n
satu kali.