Algoritma untuk mencocokkan angka dengan jumlah gerakan minimum

11

Ini adalah semacam pertanyaan jarak edit, dan sangat mudah. Saya benar-benar mati otak tentang hal ini dan tidak bisa mengetahuinya sejauh ini.


Diberikan serangkaian angka, mis

[3, 1, 1, 1]

Bagaimana cara yang paling efisien mengubah semua angka menjadi angka yang sama, dengan jumlah minimum "bergerak"? Dengan "bergerak" berarti menambah atau menghapus satu dari nomor.

Dalam contoh di atas, gerakan paling efisien adalah:

[1, 1, 1, 1]

Ini akan membutuhkan 2 gerakan, mengurangi angka pertama dua kali.

Saya tidak dapat menemukan cara terbaik untuk mengetahuinya, mengingat susunan ratusan angka yang jauh lebih besar.

Saya awalnya mencoba menghitung angka rata-rata bulat (jumlah semua dibagi dengan panjang), dan kemudian menguranginya menjadi rata-rata yang dihitung, tetapi contoh di atas mematahkan ini, membutuhkan 4 langkah alih-alih 2.

Saya kira saya bisa membayangkan:

  1. Rata-rata,
  2. Mode,
  3. Median

dan dapatkan jarak edit masing-masing, pilih jarak minimum. Namun, saya tidak yakin ini benar dalam setiap contoh. Bagaimana saya bisa tahu?

dthree
sumber
Jika domain terbatas, Anda dapat mencoba semua kemungkinan dari min hingga maks. Kalau tidak, Anda dapat mencoba menggunakan mode atau median.
Bartosz Przybylski
Terima kasih @ Bartek. Sepertinya mencoba semua kemungkinan akan sangat tidak efisien jika berhadapan dengan ratusan atau ribuan angka. Saya akan memeriksa mode / median. Tetapi apakah ini pasti akan membuahkan hasil di setiap contoh? Itu pertanyaan utama saya. Saya mencari algoritma tertentu yang efisien.
dthree
Apakah nomor harus dalam himpunan angka, atau dapatkah itu bilangan bulat?
TCSGrad
@TCSGrad Ini bisa berupa bilangan bulat apa pun, tetapi jelas Anda ingin memilih satu yang ada di antara angka min dan max. Dalam hal ini, baik 1, 2, atau 3.
dthree

Jawaban:

10

Jawabannya adalah dengan mengambil median. Salah satu sifat median adalah meminimalkan jarak L1 ke setiap elemen. (Untuk memahami artikel Wikipedia, ambil distribusi probabilitas untuk menjadi distribusi yang seragam di atas seri angka asli Anda).

Ini adalah algoritma yang memecahkan masalah (aslinya ditulis oleh dc2 ):

function median(arr) {
  arr.sort(function(a, b) { return a - b; });
  var half = floor(arr.length/2);
  if ( arr.length % 2 ) {
    return arr[half];
  } else {
    return (arr[half-1] + arr[half]) / 2.0;
  }
}

function minl1(arr) {
  var moves = 0;
  var mdn = median(arr);
  for ( var i = 0; i < arr.length; ++i ) {
    moves += Math.abs(mdn - arr[i]);
  }
  return moves;
}

minl1([3, 1, 1, 1]); // -> 2
mhum
sumber
Ya, itu berhasil. Lucu cara kerjanya. Sepertinya median tidak akan melakukannya, tapi hei. Terima kasih banyak.
dthree
1
Lihat jawaban saya untuk bukti.
Yuval Filmus
@ dc2: Anda tidak dapat "memastikan" dengan "mencobanya".
Raphael
1
Sebagai catatan: Anda dapat menghitung waktu rata-rata O (n)
Bartosz Przybylski
1
@ Raphael Apakah saya tetap bisa memasukkan kode OP dalam beberapa jawaban lain, tanpa referensi ke OP?
theouroureye
10

x1,,xnm

δ(m)=i=1n|mxi|.
δ(m+1)δ(m)
δ(m+1)δ(m)=i=1n{+1mxi1m<xi=#{i:mxi}#{i:m<xi}.
m+δ(m+1)δ(m)nnx1,,xnmδ(m+1)δ(m)0ximin(δ(x1),,δ(xn))

xinmxiδ(m+1)δ(m)=1δ(m)δ(m1)=1mnxiδxi

Yuval Filmus
sumber
Anda mungkin melewatkannya, tetapi jawaban ini (hampir) membuktikan bahwa median adalah pilihan optimal.
Yuval Filmus
1
jawaban Anda sangat bagus dan saya membatalkannya. Sayangnya bagi saya, sedikit terlalu bagus karena saya tidak begitu fasih dalam notasi ilmiah, meninggalkan sebagian besar sebagai reruntuhan. Itu masalah saya, bukan masalah Anda.
dthree
5

Masalahnya dapat dirumuskan sebagai masalah LP:

n[a1,a2...an]

min|aix|

x

xx

EDIT : Seperti yang ditunjukkan dalam komentar, fungsi objektif harus dijumlahkan berdasarkan perbedaan absolut. Untuk mengubahnya kembali menjadi LP standar, kita dapat menulis ulang LP sebagai:

minai

tunduk pada:

aiaix i
aiaix i
ai,x0 i

ai=|aix| ix

TCSGrad
sumber
Jadi jika saya mengerti ini dengan benar, dalam contoh saya, x akan menjadi 1 - 3, dan jadi saya akan menemukan jarak sunting 1, 2 dan 3, dan kemudian melakukan min pada itu?
dthree
xx
Mengapa kendala itu perlu?
Raphael