Jika Anda memiliki satu miliar angka dan seratus komputer, apa cara terbaik untuk menemukan median angka-angka ini?
Salah satu solusi yang saya miliki adalah:
- Pisahkan set secara merata di antara komputer.
- Sortir mereka.
- Temukan median untuk setiap set.
- Sortir set pada median.
- Gabungkan dua set sekaligus dari median terendah ke tertinggi.
Jika kita telah m1 < m2 < m3 ...
terlebih dahulu bergabung Set1
dan Set2
dan dalam himpunan yang dihasilkan kita dapat membuang semua angka lebih rendah dari median Set12
(digabung). Jadi pada setiap titik waktu kita memiliki set ukuran yang sama. Omong-omong, ini tidak dapat dilakukan secara paralel. Ada ide?
Jawaban:
Ah, otakku baru saja mulai bergerak, aku punya saran yang masuk akal sekarang. Mungkin terlambat jika ini adalah wawancara, tetapi tidak apa-apa:
Mesin 1 harus disebut "mesin kontrol", dan demi argumen apakah itu dimulai dengan semua data, dan mengirimkannya dalam paket yang sama ke 99 mesin lainnya, atau jika data mulai terdistribusi secara merata di antara mesin, dan itu mengirimkan 1/99 datanya ke masing-masing. Partisi tidak harus sama, cukup tutup.
Masing-masing mesin memilah datanya, dan melakukannya dengan cara yang lebih dulu menemukan nilai yang lebih rendah. Jadi misalnya quicksort, selalu mengurutkan bagian bawah partisi terlebih dahulu [*]. Ini menulis data kembali ke mesin kontrol dalam urutan yang meningkat sesegera mungkin (menggunakan asinkron IO untuk melanjutkan penyortiran, dan mungkin dengan Nagle pada: bereksperimen sedikit).
Mesin kontrol melakukan penggabungan 99-arah pada data saat diterima, tetapi membuang data yang digabungkan, hanya menjaga jumlah nilai yang dilihatnya. Ini menghitung median sebagai nilai rata-rata dari 1/2 milyar dan 1/2 milyar plus.
Ini menderita masalah "paling lambat dalam kawanan". Algoritma tidak dapat menyelesaikan sampai setiap nilai kurang dari median telah dikirim oleh mesin sortasi. Ada kemungkinan yang masuk akal bahwa satu nilai semacam itu akan cukup tinggi di dalam paket datanya. Jadi begitu partisi awal data selesai, perkiraan waktu berjalan adalah kombinasi waktu untuk menyortir 1/99 data dan mengirimkannya kembali ke komputer kontrol, dan waktu untuk kontrol membaca 1/2 data . "Kombinasi" ada di suatu tempat antara maksimum dan jumlah dari waktu-waktu itu, mungkin mendekati maks.
Insting saya adalah bahwa untuk mengirim data melalui jaringan menjadi lebih cepat daripada menyortirnya (apalagi hanya memilih median) itu perlu jaringan yang sangat cepat. Mungkin prospek yang lebih baik jika jaringan dapat dianggap instan, misalnya jika Anda memiliki 100 core dengan akses yang sama ke RAM yang berisi data.
Karena jaringan I / O cenderung terikat, mungkin ada beberapa trik yang dapat Anda mainkan, setidaknya untuk data yang kembali ke mesin kontrol. Misalnya, alih-alih mengirim "1,2,3, .. 100", mungkin mesin sortir dapat mengirim pesan yang berarti "100 nilai kurang dari 101". Mesin kontrol kemudian dapat melakukan penggabungan yang dimodifikasi, di mana ia menemukan paling sedikit dari semua nilai-nilai top-of-a-range, kemudian memberitahu semua mesin sortir apa itu, sehingga mereka dapat (a) memberi tahu mesin kontrol bagaimana banyak nilai untuk "dihitung" di bawah nilai itu, dan (b) melanjutkan pengiriman data yang diurutkan dari titik itu.
Secara umum, mungkin ada permainan tebak tantangan-respons yang cerdas yang dapat dimainkan oleh mesin kontrol dengan 99 mesin sortir.
Ini melibatkan bolak-balik di antara mesin, yang dihindari versi pertama saya yang lebih sederhana. Saya tidak benar-benar tahu bagaimana memperkirakan kinerja relatif mereka, dan karena pertukaran itu rumit, saya membayangkan ada banyak solusi yang lebih baik di luar sana daripada apa pun yang akan saya pikirkan sendiri, dengan asumsi ini adalah masalah nyata.
[*] tumpukan yang tersedia memungkinkan - pilihan Anda untuk melakukan bagian mana yang dibatasi terlebih dahulu jika Anda tidak memiliki ruang ekstra O (N). Tetapi jika Anda memiliki cukup ruang ekstra, Anda dapat memilih, dan jika Anda tidak memiliki cukup ruang, Anda setidaknya dapat menggunakan apa yang Anda lakukan untuk memotong beberapa sudut, dengan melakukan bagian kecil terlebih dahulu untuk beberapa partisi pertama.
sumber
sumber
time
perintah yang diterapkan pada seluruh pipa, butuhreal=36m24s
("waktu jam dinding"),user=113m15s
("waktu paralel", semua core ditambahkan). Perintah terpanjang, jauh di depan yang lain, adalahsort
, bahkan jika itu berulir ke empat core saya di 100%. Konsumsi RAM sangat diterima.Saya benci menjadi pelawan di sini, tapi saya tidak percaya penyortiran diperlukan, dan saya pikir algoritma apa pun yang melibatkan penyortiran satu miliar / 100 angka akan lambat. Mari pertimbangkan algoritma pada satu komputer.
1) Pilih 1000 nilai secara acak dari miliar, dan gunakan untuk mendapatkan ide distribusi angka, terutama rentang.
2) Alih-alih menyortir nilai, alokasikan ke ember berdasarkan distribusi yang baru saja Anda hitung. Jumlah ember dipilih agar komputer dapat menanganinya secara efisien, tetapi seharusnya sebesar kenyamanan. Rentang bucket harus sedemikian sehingga kira-kira jumlah nilai yang sama masuk dalam setiap bucket (ini tidak penting untuk algoritme, tetapi ini membantu efisiensi. 100.000 ember mungkin sesuai). Catat jumlah nilai dalam setiap ember. Ini adalah proses O (n).
3) Cari tahu ember mana yang rentang median terletak. Ini dapat dilakukan dengan hanya memeriksa jumlah total di setiap ember.
4) Temukan median aktual dengan memeriksa nilai-nilai dalam ember itu. Anda dapat menggunakan pengurutan di sini jika mau, karena Anda hanya mengurutkan sekitar 10.000 angka. Jika jumlah nilai dalam ember itu besar maka Anda dapat menggunakan algoritme ini lagi hingga Anda memiliki jumlah yang cukup kecil untuk disortir.
Pendekatan ini diparalelkan secara sepele dengan membagi nilai antara komputer. Setiap komputer melaporkan total dalam setiap ember ke komputer 'kontrol' yang melakukan langkah 3. Untuk langkah 4 setiap komputer mengirimkan nilai (diurutkan) dalam ember yang relevan ke komputer kontrol (Anda juga dapat melakukan kedua algoritma secara paralel, tapi mungkin tidak sepadan).
Total proses adalah O (n), karena kedua langkah 3 dan 4 adalah sepele, asalkan jumlah ember cukup besar.
sumber
Satu miliar sebenarnya tugas yang cukup membosankan untuk komputer modern. Kita berbicara tentang 4 GB senilai 4 byte integer di sini ... 4 GB ... itu adalah RAM dari beberapa smartphone.
Output pada mesin saya:
Jadi ini selesai pada mesin saya dalam waktu kurang dari dua menit (1:43 yang 0:10 menghasilkan angka acak) menggunakan inti tunggal dan bahkan melakukan pengurutan penuh. Tidak ada yang benar-benar mewah.
Ini tentunya merupakan tugas yang menarik untuk set angka yang lebih besar. Saya hanya ingin menegaskan: satu miliar adalah kacang. Jadi pikirkan dua kali sebelum Anda mulai memberikan solusi kompleks pada tugas-tugas yang sangat sederhana;)
sumber
(numbers[numbers.length / 2]+numbers[numbers.length / 2+1])/2
jikanumbers.length
adalah genap dannumbers[numbers.length / 2]
hanya jikanumbers.length
aneh.The estimasi statistik agar seperti persentil median dan 99 dapat didistribusikan secara efisien dengan algoritma seperti t-mencerna atau Q-dicerna .
Dengan menggunakan salah satu algoritma, setiap node menghasilkan intisari, yang mewakili distribusi nilai yang disimpan secara lokal. Intisari dikumpulkan pada satu simpul tunggal, digabung (secara efektif menjumlahkan distribusi), dan median atau persentil lainnya kemudian dapat dilihat.
Pendekatan ini digunakan oleh elasticsearch dan, mungkin, BigQuery (mengikuti deskripsi fungsi QUANTILES).
sumber
Median untuk set angka ini
2, 3, 5, 7, 11, 13, 67, 71, 73, 79, 83, 89, 97
adalah 67.
Median untuk set angka ini
2, 3, 5, 7, 11, 13, 67, 71, 73, 79, 83, 89
adalah 40.
Dengan asumsi pertanyaan adalah sekitar 1.000.000.000 bilangan bulat (x) di mana 0> = x <= 2.147.483.647 dan bahwa OP sedang mencari (elemen (499.999.999) + elemen (500.000.000)) / 2 (jika angka-angka itu diurutkan). Juga dengan asumsi bahwa semua 100 komputer semuanya sama.
menggunakan laptop dan GigE saya ...
Apa yang saya temukan adalah laptop saya dapat mengurutkan 10.000.000 Int32 dalam 1,3 detik. Jadi perkiraan kasarnya adalah bahwa semacam miliar angka akan mengambil 100 x 1,3 detik (2 menit 10 detik);).
Perkiraan transfer file satu arah dari file 40MB pada gigabit Ethernet adalah 0,32 detik. Ini berarti bahwa hasil yang diurutkan dari semua komputer akan dikembalikan dalam waktu sekitar 32 detik (komputer 99 tidak mendapatkan file-nya sampai 30 detik setelah start). Dari sana tidak perlu waktu lama untuk membuang yang terendah 499.999.998 angka, tambahkan 2 berikutnya dan bagi 2.
sumber
a*(1e7)log(1e7) = 1.3sec
=>a = 1.6e-9sec
=>a*(1e9)log(1e9) ~ 167sec
, jadi perkiraan Anda tidak terlalu buruk.Ini mungkin mengejutkan orang, tetapi jika bilangan bulat cukup kecil untuk muat di dalam 32-bit (atau lebih kecil) - Lakukan saja semacam ember! Hanya membutuhkan 16GB ram untuk sejumlah int 32-bit dan berjalan di O (n), yang akan mengungguli semua sistem terdistribusi untuk n masuk akal, misalnya satu miliar.
Setelah Anda memiliki daftar yang disortir, itu sepele untuk memilih median. Bahkan, Anda tidak perlu membuat daftar yang disortir, tetapi hanya melihat ember yang harus melakukannya.
Implementasi sederhana ditunjukkan di bawah ini. Hanya berfungsi untuk bilangan bulat 16-bit, tetapi ekstensi ke 32-bit seharusnya mudah.
Menggunakan file teks dengan satu miliar (10 9 ) angka dan berjalan dengan
time
seperti itumenghasilkan waktu berjalan pada mesin saya 1m49.293s. Sebagian besar waktu yang berjalan mungkin adalah disk IO juga.
sumber
Anehnya, saya pikir jika Anda memiliki cukup komputer, Anda lebih baik menyortir daripada menggunakan
O(n)
algoritma median-finding. (Kecuali jika inti Anda sangat, sangat lambat, saya hanya akan menggunakan satu dan menggunakanO(n)
algoritma mencari median hanya untuk angka 1e9; namun jika Anda memiliki 1e12, itu mungkin kurang praktis.)Bagaimanapun, anggaplah kita memiliki lebih dari satu log n core untuk mengatasi masalah ini, dan kita tidak peduli dengan konsumsi daya, hanya mendapatkan jawabannya dengan cepat. Mari kita asumsikan bahwa ini adalah mesin SMP dengan semua data yang sudah dimuat dalam memori. (Misalnya, mesin 32-core Sun dari jenis ini.)
Satu utas memotong daftar secara membabi buta menjadi potongan berukuran sama dan memberi tahu utas M lainnya untuk menyortirnya. Utas itu rajin melakukannya,
(n/M) log (n/M)
tepat waktu. Mereka kemudian mengembalikan tidak hanya median mereka, tetapi, katakanlah, persentil ke 25 dan 75 mereka juga (kasus terburuk yang jahat lebih baik jika Anda memilih angka yang sedikit berbeda). Sekarang Anda memiliki rentang data 4M. Anda kemudian mengurutkan rentang ini dan bekerja ke atas melalui daftar sampai Anda menemukan nomor sehingga, jika Anda membuang setiap rentang yang lebih kecil dari atau berisi nomor, Anda akan membuang separuh data Anda. Itu batas bawah Anda untuk median. Lakukan hal yang sama untuk batas atas. Ini membutuhkanM log M
waktu, dan semua core harus menunggu, jadi itu benar-benar sia-siaM^2 log M
waktu potensial. Sekarang Anda memiliki utas tunggal Anda memberi tahu orang lain untuk melemparkan semua data di luar rentang (Anda harus membuang sekitar setengah pada setiap pass) dan ulangi - ini adalah operasi yang sangat cepat karena data sudah diurutkan. Anda tidak perlu mengulangi ini lebih dari beberapalog(n/M)
kali sebelum lebih cepat untuk hanya mengambil data yang tersisa dan menggunakanO(n)
pencari median standar di atasnya.Jadi, kompleksitas total adalah sesuatu seperti
O((n/M) log (n/M) + M^2 log M log (n/M))
. Dengan demikian, ini lebih cepat daripadaO(n)
jenis median pada satu inti jikaM >> log(n/M)
danM^3 log M < n
, yang berlaku untuk skenario yang telah Anda jelaskan.Saya pikir ini adalah ide yang sangat buruk mengingat betapa tidak efisiennya, tetapi lebih cepat.
sumber
n
danM
merupakan variabel yang dapat menskala secara sewenang-wenang, jadi salah satunya termasuk keduanya. Secara khusus, saya mendalilkan ituM
>log n
, yang berarti bahwa jika Anda peduli itun log n
bukan hanyan
, Anda harus peduliM
juga.Ini dapat dilakukan lebih cepat daripada algoritma yang dipilih (n log n)
- Statistik pesanan Algoritma pemilihan terdistribusi - O (n)
Sederhanakan masalah dengan masalah awal dalam menemukan nomor k dalam array yang tidak disortir.
- Menghitung pengurutan histogram O (n)
Anda harus mengasumsikan beberapa properti tentang kisaran angka - dapatkah kisaran cocok dalam memori? - Urutan gabungan eksternal - O (n log n) - dijelaskan di atas.
Anda pada dasarnya mengurutkan angka pada pass pertama, kemudian menemukan median pada yang kedua.
- Jika ada yang diketahui tentang distribusi angka, algoritma lain dapat dihasilkan.
Untuk detail dan implementasi lebih lanjut, lihat:
http://www.fusu.us/2013/07/median-in-large-set-across-1000-servers.html
sumber
Satu komputer lebih dari cukup untuk menyelesaikan masalah.
Tapi mari kita asumsikan ada 100 komputer. Satu-satunya hal rumit yang harus Anda lakukan adalah mengurutkan daftar. Membagi menjadi 100 bagian, mengirim satu bagian ke setiap komputer, membiarkannya disortir di sana, dan menggabungkan bagian-bagian setelah itu.
Kemudian ambil nomor dari tengah daftar yang disortir (yaitu dengan indeks 5 000 000 000).
sumber
Itu tergantung pada data Anda. Skenario kasus terburuk adalah bahwa angka itu terdistribusi secara seragam.
Dalam hal ini Anda dapat menemukan median dalam waktu O (N) seperti dalam contoh ini:
Misalkan angka Anda adalah 2,7,5,10,1,6,4,4,6,10,4,7,1,8,4,9,9,3,4,3 (kisaran 1-10) .
Kami membuat 3 ember: 1-3, 4-7, 8-10. Perhatikan bahwa atas dan bawah memiliki ukuran yang sama.
Kami mengisi ember dengan angka, menghitung berapa banyak yang jatuh masing-masing, maksimal dan minimum
Berarti jatuh di ember tengah, kami mengabaikan sisanya
Kami membuat 3 ember: 4, 5-6, 7. Rendah akan mulai dengan hitungan 5 dan dengan maksimal 3 dan tinggi dengan minimal 8 dan hitungan 5.
Untuk setiap angka, kami menghitung berapa banyak yang jatuh di ember rendah dan tinggi, maks dan minimum, dan simpan ember tengah.
Sekarang kita dapat menghitung median secara langsung: kita memiliki situasi seperti ini
jadi mediannya adalah 4,5.
Dengan asumsi Anda tahu sedikit tentang distribusi, Anda dapat menyesuaikan cara menentukan rentang untuk mengoptimalkan kecepatan. Bagaimanapun, kinerja harus pergi dengan O (N), karena 1 + 1/3 + 1/9 ... = 1,5
Anda perlu min dan maks karena tepi kasus (mis. Jika median adalah rata-rata antara maks rendah lama dan elemen berikutnya).
Semua operasi ini dapat diparalelkan, Anda dapat memberikan 1/100 data ke setiap komputer dan menghitung 3 ember di setiap node, lalu mendistribusikan ember yang Anda simpan. Ini lagi membuat Anda menggunakan jaringan secara efisien karena setiap angka dilewatkan rata-rata 1,5 kali (jadi O (N)). Anda bahkan dapat mengalahkan itu jika Anda hanya melewatkan angka minimal di antara node (mis. Jika simpul 1 memiliki 100 angka dan simpul 2 memiliki angka 150, maka simpul 2 dapat memberikan 25 angka ke simpul 1).
Kecuali Anda tahu lebih banyak tentang distribusi, saya ragu Anda bisa melakukan lebih baik daripada O (N) di sini, karena Anda benar-benar perlu menghitung elemen setidaknya sekali.
sumber
O(n log n)
dalam kasus itu. Apakah masuk akal ? Ngomong-ngomong, aku suka idemuo(n)+o(n/3)+o(n/9)+...
yang diamo(n)
dan tidako(n log n)
.o(n)
dalam kasus itu, dengan partisi yang naif.Metode yang lebih mudah adalah memiliki angka tertimbang.
sumber
Pisahkan 10 ^ 9 angka, 10 ^ 7 untuk setiap komputer ~ 80MB untuk masing-masing. Setiap komputer mengurutkan angkanya. Kemudian komputer 1 menggabungkan-mengurutkan angka-angka sendiri dengan yang dari komputer 2, komputer 3 dan 4, dll ... Kemudian komputer 1 menulis setengah dari angka-angka kembali ke 2, 3 hingga 4, dll. Kemudian 1 menggabungkan jenis angka-angka dari komputer 1,2,3,4, tulis kembali. Dan seterusnya. Bergantung pada ukuran RAM pada komputer yang Anda gunakan untuk tidak menulis semua angka kembali ke masing-masing komputer, Anda mungkin dapat mengakumulasikan angka pada komputer 1 untuk beberapa langkah, tetapi Anda melakukan perhitungan.
Oh, akhirnya dapatkan nilai rata-rata 500000000 dan 500000001st (tapi periksa ada cukup 00 di sana, saya belum).
EDIT: @Roman - baik jika Anda tidak percaya bahkan itu benar maka tidak ada gunanya saya mengungkapkan kebenaran atau kepalsuan proposisi. Apa yang saya maksudkan adalah bahwa kekuatan brutal terkadang mengalahkan kecerdasan dalam suatu perlombaan. Butuh waktu sekitar 15 detik untuk menyusun algoritma yang saya yakin bisa diterapkan, yang akan berfungsi, dan yang akan dapat disesuaikan dengan berbagai ukuran input dan jumlah komputer, dan dapat disesuaikan dengan karakteristik komputer dan pengaturan jaringan. Jika diperlukan, atau siapa pun, katakan 15 menit untuk menyusun algoritma yang lebih canggih, saya memiliki keunggulan 14m45 untuk menyusun solusi saya dan mulai menjalankannya.
Tapi saya dengan bebas mengakui ini semua pernyataan, saya belum mengukur apa pun.
sumber
Ini bisa dilakukan pada node menggunakan data yang tidak diurutkan melintasi node (katakanlah dari file log) dengan cara berikut.
Ada 1 simpul orangtua dan 99 simpul anak. Node anak memiliki dua panggilan api:
Node induk memanggil stats () pada semua node anak, mencatat minimum dan maksimum semua node.
Pencarian biner sekarang dapat dilakukan dengan cara berikut:
Ada 1 simpul orangtua dan 99 simpul anak. Node anak memiliki dua panggilan api:
Node induk memanggil stats () pada semua node anak, mencatat minimum dan maksimum semua node.
Pencarian biner sekarang dapat dilakukan dengan cara berikut:
Jika statistik () dan bandingkan () dapat dihitung sebelumnya dengan jenis O (N / Mlogn / M), maka pra-perhitungan O (N / M) dengan kompleksitas memori O (N) untuk pra- perhitungan. Kemudian Anda dapat melakukan perbandingan () dalam waktu yang konstan, sehingga semuanya (termasuk pra-perhitungan) akan berjalan di O (N / MlogN / M) + O (logN)
Beri tahu saya jika saya melakukan kesalahan!
sumber
Bagaimana dengan ini: - setiap node dapat mengambil 1Billion / 100 angka. Pada setiap node elemen dapat diurutkan dan median dapat ditemukan. Temukan median median. kita bisa, dengan menjumlahkan jumlah angka yang kurang dari median-of-median pada semua node mengetahui x%: y% split yang dibuat median-of-median. Sekarang minta semua node untuk menghapus elemen kurang dari median median (mengambil contoh 30%: 70% split) .30% angka dihapus. 70% dari 1 Milyar adalah 700 juta. Sekarang semua node yang menghapus kurang dari 3 juta node dapat mengirim kembali node-node tambahan itu ke komputer utama. Komputer utama mendistribusikan kembali sedemikian rupa sehingga sekarang semua node akan memiliki jumlah node yang hampir sama (7 juta). Sekarang masalahnya berkurang menjadi angka 700 juta .... terus berlanjut hingga kita memiliki set yang lebih kecil yang dapat dihitung pada satu komputer.
sumber
Pertama-tama mari kita cari cara menemukan median n angka pada satu mesin: Saya pada dasarnya menggunakan strategi partisi.
Masalah: pemilihan (n, n / 2): Temukan nomor n / 2 dari angka terkecil.
Anda memilih mengatakan elemen tengah k dan data partisi menjadi 2 sub array. 1 berisi semua elemen <k dan 2 berisi semua elemen> = k.
jika sizeof (sub-array 1)> = n / 2, Anda tahu bahwa sub-array ini berisi median. Anda kemudian dapat membuang sub-array ke-2. Selesaikan pemilihan masalah ini (ukuran sub-array 1, n / 2) .
Dalam kasus lain, buang subarray 1 ini dan selesaikan seleksi (subarray kedua, n / 2 - sizeof (subarray 1)
Lakukan secara rekursif.
kompleksitas waktu adalah O (n) waktu yang diharapkan.
Sekarang jika kita memiliki banyak mesin, dalam setiap iterasi, kita harus memproses array untuk dibagi, kita mendistribusikan array ke mesin yang berbeda. Setiap mesin memproses sejumlah array dan mengirimkan kembali ringkasan ke mesin pengontrol hub yaitu ukuran subarray pertama dan ukuran subarray kedua. Mesin hub menambahkan ringkasan dan memutuskan subarray mana (1 atau 2) untuk memproses lebih lanjut dan parameter pemilihan 2 dan mengirimkannya kembali ke setiap mesin. dan seterusnya.
Algoritma ini dapat diimplementasikan dengan sangat rapi menggunakan peta reduksi?
Bagaimana kelihatannya?
sumber
Saya pikir jawaban Steve Jessop akan menjadi yang tercepat.
Jika ukuran transfer data jaringan adalah hambatan, berikut adalah pendekatan lain.
sumber
Saya akan melakukannya seperti ini:
pada awalnya semua 100 pekerjaan untuk menemukan angka tertinggi dan terendah; setiap komputer memiliki bagiannya dari database / file yang ditanyakannya;
ketika angka tertinggi dan terendah ditemukan, satu komputer membaca data, dan mendistribusikan setiap angka, secara merata, ke 99 lainnya; jumlahnya didistribusikan dengan interval yang sama; (satu dapat mengambil dari -100 juta hingga 0, yang lain - dari 0 hingga 100 juta, dll);
Saat menerima angka, masing-masing dari 99 komputer sudah mengurutkannya;
Maka, mudah untuk menemukan median ... Lihat berapa banyak angka yang memiliki masing-masing komputer, tambahkan semuanya (jumlah dari berapa angka yang ada, bukan angka itu sendiri), bagi dengan 2; menghitung di mana komputer adalah angka, dan indeks mana;
:) voilla
PS Sepertinya ada banyak kebingungan di sini; MEDIAN - adalah NOMOR DI TENGAH-TENGAH DAFTAR NOMOR!
sumber
Anda dapat menggunakan metode pohon turnamen untuk menemukan median. Kita dapat membuat pohon dengan 1000 node meninggalkan sehingga setiap node daun adalah array. Kami kemudian melakukan turnamen n / 2 antara berbagai array. Nilai pada root setelah turnamen n / 2 adalah hasilnya.
http://www.geeksforgeeks.org/tournament-tree-and-binary-heap/
sumber
Jika angkanya tidak berbeda, dan hanya milik rentang tertentu, yaitu diulang, maka solusi sederhana yang muncul di benak saya adalah mendistribusikan angka-angka di antara 99 mesin secara merata, dan menjadikan satu mesin sebagai master. Sekarang setiap mesin mengulangi angka-angka yang diberikan, dan menyimpan hitungan masing-masing angka dalam satu set hash. Setiap kali angka diulang dalam himpunan angka yang dialokasikan untuk komputer tertentu, ia memperbarui hitungannya dalam hash set.
Semua mesin kemudian mengembalikan hash set ke mesin master. Mesin master menggabungkan set hash, menjumlahkan jumlah kunci yang sama yang ditemukan dalam set hash. Misalnya set hash mesin # 1 memiliki entri ("1", 7), dan set hash mesin # 2 memiliki entri ("1", 9), jadi mesin master saat menyisir set hash membuat entri dari ("1", 16), dan seterusnya.
Setelah hash set telah digabung, maka cukup sortir kunci, dan sekarang Anda dapat dengan mudah menemukan item th (n / 2) dan item th (n + 2/2), dari hash set yang diurutkan.
Metode ini tidak akan bermanfaat jika angka miliar berbeda.
sumber
Nah, misalkan Anda tahu bahwa jumlah bilangan bulat yang berbeda adalah (katakanlah) 4 miliar, maka Anda dapat memasukkannya ke dalam ember 64k dan mendapatkan jumlah yang didistribusikan untuk setiap ember dari setiap mesin di cluster (100 komputer). Gabungkan semua jumlah ini. Sekarang, cari ember yang memiliki median, dan kali ini hanya meminta ember untuk elemen 64k yang akan terletak di ember target Anda. Ini membutuhkan O (1) (khusus 2) kueri atas "gugus" Anda. : D
sumber
Nilai sen saya, setelah semua yang telah dibesarkan oleh orang lain:
Menemukan median pada satu mesin adalah O (N): https://en.wikipedia.org/wiki/Selection_algorithm .
Mengirim nomor N ke 100 mesin juga O (N). Jadi, untuk membuat menggunakan 100 mesin menarik, komunikasi harus relatif cepat, atau N begitu besar sehingga satu mesin tidak dapat mengatasinya ketika N / 100 dapat dilakukan, atau kami hanya ingin mempertimbangkan masalah matematika tanpa peduli tentang komunikasi data.
Singkatnya, saya berasumsi bahwa dalam batas yang wajar, kami dapat mengirim / mendistribusikan angka tanpa memengaruhi analisis efisiensi.
Pertimbangkan pendekatan berikut, di mana satu mesin ditugaskan untuk menjadi "master" untuk beberapa pemrosesan umum. Ini akan relatif cepat, sehingga "master" juga berpartisipasi dalam tugas-tugas umum yang dilakukan setiap mesin.
Kompleksitas waktu:
sumber
Bagilah 1 miliar angka menjadi 100 mesin. Setiap mesin akan memiliki 10 ^ 7 angka.
Untuk setiap nomor yang masuk ke mesin, simpan nomor itu di peta frekuensi, angka -> hitung. Juga simpan nomor min di setiap mesin.
Temukan median di setiap mesin: mulai dari angka minimum di setiap mesin, jumlah penghitungan hingga indeks median tercapai. Median di setiap mesin, akan menjadi sekitar. lebih rendah dan lebih besar dari 5 * 10 ^ 6 angka.
Temukan median semua median, yang akan lebih rendah dan lebih besar dari kira-kira. 50 * 10 ^ 7 angka, yang merupakan median 1 miliar angka.
Sekarang beberapa optimasi dari langkah ke-2: Alih-alih menyimpan dalam peta frekuensi, simpan hitungan dalam array bit variabel. Sebagai contoh: Mari kita mulai dari nomor min di mesin, ini adalah jumlah frekuensi:
Di atas dapat disimpan dalam bit array sebagai:
Perhatikan bahwa secara keseluruhan biayanya sekitar 10 ^ 7 bit untuk setiap mesin, karena setiap mesin hanya menangani 10 ^ 7 angka. 10 ^ 7bits = 1.25 * 10 ^ 6 byte, yaitu 1.25MB
Jadi dengan pendekatan di atas, setiap mesin akan membutuhkan ruang 1,25MB untuk menghitung median lokal. Dan median median dapat dihitung dari 100 median lokal, menghasilkan median 1 miliar angka.
sumber
Saya menyarankan metode untuk menghitung sekitar Median. :) Jika satu miliar angka ini dalam urutan acak, saya pikir saya dapat memilih 1/100 atau 1/10 dari satu miliar angka secara acak, urutkan dengan 100 mesin, lalu pilih mediannya. Atau mari kita bagi miliar angka dalam 100 bagian, biarkan setiap mesin memilih 1/10 dari setiap bagian secara acak, hitung mediannya. Setelah itu kita memiliki 100 angka dan kita dapat menghitung median angka 100 lebih mudah. Hanya saran, saya tidak yakin apakah itu benar secara matematis. Tapi saya pikir Anda bisa menunjukkan hasilnya kepada manajer yang tidak terlalu pintar matematika.
sumber
Jawaban Steve Jessop salah:
pertimbangkan empat kelompok berikut:
{2, 4, 6, 8, 10}
{21, 21, 24, 26, 28}
{12, 14, 30, 32, 34}
{16, 18, 36, 38, 40}
Median adalah 21, yang terkandung dalam kelompok kedua.
Median dari empat kelompok adalah 6, 24, 30, 36, Total median adalah 27.
Jadi setelah loop pertama, empat grup akan menjadi:
{6, 8, 10}
{24, 26, 28}
{12, 14, 30}
{16, 18, 36}
21 sudah salah dibuang.
Algoritma ini hanya mendukung kasus ketika ada dua kelompok.
sumber