Ini diminta dari saya dalam sebuah wawancara dan ini adalah solusi yang saya berikan:
public static int[] merge(int[] a, int[] b) {
int[] answer = new int[a.length + b.length];
int i = 0, j = 0, k = 0;
while (i < a.length && j < b.length)
{
if (a[i] < b[j])
{
answer[k] = a[i];
i++;
}
else
{
answer[k] = b[j];
j++;
}
k++;
}
while (i < a.length)
{
answer[k] = a[i];
i++;
k++;
}
while (j < b.length)
{
answer[k] = b[j];
j++;
k++;
}
return answer;
}
Apakah ada cara yang lebih efisien untuk melakukan ini?
Sunting: Metode panjang yang dikoreksi.
while (i < a.length && j < b.length) answer[k++] = a[i] < b[j] ? a[i++] : b[j++];
Spesifikasi Bahasa Jawa: Operator Bersyarat? : .Jawaban:
Sebuah perbaikan kecil, tetapi setelah loop utama, Anda bisa menggunakan
System.arraycopy
untuk menyalin ekor dari array input ketika Anda sampai ke ujung yang lain. Itu tidak akan mengubahO(n)
karakteristik kinerja solusi Anda.sumber
Sedikit lebih kompak tetapi persis sama!
sumber
Saya terkejut tidak ada yang menyebutkan implementasi yang jauh lebih keren, efisien dan ringkas ini:
Tempat Menarik
System.arraycopy
akan menang karena secara internal dapat melakukan ini dengan instruksi perakitan x86 tunggal.a[i] >= b[j]
bukana[i] > b[j]
. Ini menjamin "stabilitas" yang didefinisikan ketika elemen a dan b sama, kita menginginkan elemen dari a sebelum b.sumber
j < 0
,b
sudah habis, jadi kami terus menambahkana
elemen yang tersisa keanswer
arraySetiap perbaikan yang dapat dilakukan akan berupa optimalisasi mikro, algoritma keseluruhan sudah benar.
sumber
System.arrayCopy()
sangat cepat karena menggunakanmemcpy
panggilan yang dioptimalkan oleh CPU . Jadi ada ruang untuk meningkatkan kinerja dengan menyalin potongan. Ada juga ruang lingkup untuk pencarian batas biner.Solusi ini juga sangat mirip dengan posting lain kecuali menggunakan System.arrayCopy untuk menyalin elemen array yang tersisa.
sumber
Di sini adalah fungsi yang diperbarui. Ini menghapus duplikat, semoga seseorang akan menemukan ini dapat digunakan:
sumber
Itu bisa dilakukan dalam 4 pernyataan seperti di bawah ini
sumber
sort
fungsi tidak dapat menggunakan dirinya sendiri sebagai metode penyortiran. Itu akan menjadi kemunduran tanpa batas alih-alih rekursi. Premis lainnya adalah merge_array adalah fungsi yang mengimplementasikan sort. Dengan demikian jawaban ini tidak dapat digunakan dalam konteks yang paling mungkin.Saya harus menulisnya dalam javascript, ini dia:
sumber
Koleksi Apache mendukung metode susun sejak versi 4; Anda dapat melakukan ini menggunakan
collate
metode di:Berikut kutipan dari javadoc:
Jangan menemukan kembali roda! Referensi dokumen: http://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/CollectionUtils.html
sumber
Gabung GallopSearch: O (log (n) * log (i)) daripada O (n)
Saya pergi ke depan dan menerapkan saran greybeard di komentar. Terutama karena saya memerlukan versi misi kritis yang sangat efisien dari kode ini.
Ini harus menjadi cara paling efisien untuk melakukan ini, dengan kompleksitas waktu O (log (n) * log (i)) daripada O (n). Dan kompleksitas waktu kasus terburuk O (n). Jika array Anda kasar dan memiliki nilai string yang panjang, ini akan membuat cara lain untuk melakukannya lebih kecil, jika tidak maka hanya akan lebih baik daripada mereka.
Ini memiliki dua nilai baca di ujung array gabungan dan nilai tulis dalam array hasil. Setelah mengetahui nilai akhir mana yang kurang, ia melakukan pencarian gallop ke dalam array itu. 1, 2, 4, 8, 16, 32, dll. Ketika menemukan rentang di mana nilai baca array lain lebih besar. Ini biner mencari ke dalam rentang itu (memotong kisaran menjadi dua, mencari setengah yang benar, ulangi sampai nilai tunggal). Kemudian array akan menyalin nilai-nilai tersebut ke posisi penulisan. Perlu diingat bahwa salinan tersebut, secara tidak sengaja, dipindahkan sedemikian rupa sehingga tidak dapat menimpa nilai yang sama dari array pembacaan (yang berarti array penulisan dan array baca dapat sama). Itu kemudian melakukan operasi yang sama untuk array lain yang sekarang dikenal kurang dari nilai baca baru array lainnya.
Ini harus menjadi cara paling efisien untuk melakukannya.
Beberapa jawaban memiliki kemampuan menghapus duplikat. Itu akan membutuhkan algoritma O (n) karena Anda harus benar-benar membandingkan setiap item. Jadi inilah yang berdiri sendiri untuk itu, untuk diterapkan setelah fakta. Anda tidak dapat berpacu melalui beberapa entri secara keseluruhan jika Anda perlu melihat semuanya, meskipun Anda bisa berpacu melalui duplikat, jika Anda memiliki banyak entri.
Pembaruan: Jawaban sebelumnya, bukan kode yang mengerikan tetapi jelas lebih rendah daripada yang di atas.
Hyper-optimasi yang tidak perlu. Itu tidak hanya memanggil arraycopy untuk bit akhir, tetapi juga untuk awal. Memproses setiap pengantar non-tumpang tindih dalam O (log (n)) oleh binarySearch ke dalam data. O (log (n) + n) adalah O (n) dan dalam beberapa kasus efeknya akan sangat jelas terutama hal-hal seperti di mana tidak ada tumpang tindih antara array yang menggabungkan sama sekali.
sumber
That is totally what the implemented Arrays.sort does
( Bahwa : dari revisi pertama jawaban Anda - atau - dari komentar 19 Februari?) - tidak dapat ditemukan di JDK 8 Sunsoft: implementasi manaArrays.sort
yang Anda maksud?Berikut formulir singkat yang ditulis dalam javascript:
sumber
sumber
a[mid+1 .. hi]
keaux
untuk?Saya pikir memperkenalkan daftar lewati untuk array yang lebih besar diurutkan dapat mengurangi jumlah perbandingan dan dapat mempercepat proses menyalin ke dalam array ketiga. Ini bisa bagus jika array terlalu besar.
sumber
sumber
sumber
for (int i, j, k = i = j = 0 ; k < c.length ; ) c[k++] = b.length <= j || i < a.length && a[i] < b[j] ? a[i++] : b[j++];
. Apa bedanya dengan jawaban Andrew 2014 ?Algoritma dapat ditingkatkan dengan banyak cara. Misalnya, masuk akal untuk memeriksa, apakah
a[m-1]<b[0]
ataub[n-1]<a[0]
. Dalam setiap kasus itu, tidak perlu melakukan perbandingan lebih banyak. Algoritma hanya bisa menyalin array sumber dalam yang dihasilkan dalam urutan yang benar.Perangkat tambahan yang lebih rumit mungkin termasuk mencari bagian interleaving dan menjalankan algoritma penggabungan hanya untuk mereka. Ini bisa menghemat banyak waktu, ketika ukuran array yang digabung berbeda dalam skor kali.
sumber
Masalah ini terkait dengan algoritma mergesort, di mana dua sub-array yang diurutkan digabungkan menjadi satu sub-array yang diurutkan. The CLRS buku memberikan contoh dari algoritma dan membersihkan kebutuhan untuk memeriksa apakah akhirnya telah tercapai dengan menambahkan nilai sentinel (sesuatu yang membandingkan dan "lebih besar dari nilai lain") ke akhir setiap array.
Saya menulis ini dengan Python, tetapi harus diterjemahkan dengan baik ke Java juga:
sumber
Anda bisa menggunakan 2 utas untuk mengisi array yang dihasilkan, satu dari depan, satu dari belakang.
Ini dapat bekerja tanpa sinkronisasi apa pun dalam hal angka, misalnya jika setiap utas memasukkan setengah dari nilai.
sumber
sumber
sumber
sumber
Bahasa pemrograman favorit saya adalah JavaScript
sumber
Mungkin menggunakan System.arraycopy
sumber
Output adalah:
1, 2, 3, 4, 5, 6, 8, 9, 10, 100, 999, 1001,
sumber
arr2
bukanind2
, tapitemp
.Anda dapat menggunakan operator ternary untuk membuat kode sedikit lebih kompak
sumber
Hanya sedikit berbeda dari solusi aslinya
sumber
Untuk mengisi dua array yang diurutkan dalam kompleksitas waktu O (m + n) gunakan pendekatan di bawah ini dengan satu loop saja. m dan n adalah panjang array pertama dan array kedua.
sumber
sumber
Karena pertanyaannya tidak menggunakan bahasa tertentu. Berikut ini solusinya dengan Python. Dengan asumsi array sudah diurutkan.
Pendekatan 1 - menggunakan array numpy: import numpy
Pendekatan 2 - Menggunakan daftar, dengan asumsi daftar diurutkan.
sumber
Since the question doesn't assume any specific language
dari 2011/5/11/19: 43, ini ditandai java ..sort()
adalahO(n log n)
yang terbaikBerikut ini adalah implementasi java saya yang menghapus duplikat.
sumber