Minimum hareket sayısı ile sayıları eşleştirmek için algoritma


11

Bu bir çeşit mesafe düzenleme sorusudur ve çok kolaydır. Bu konuda sadece beyin ölüyüm ve şimdiye kadar çözemiyorum.


Bir dizi sayı verildiğinde, ör.

[3, 1, 1, 1]

Minimum sayı "hamle" sayısıyla tüm sayılar nasıl en verimli şekilde aynı sayıya dönüştürülür? "Hareket", bir sayıya bir tane eklemek veya çıkarmak anlamına gelir.

Yukarıdaki örnekte, en etkili hamleler şöyledir:

[1, 1, 1, 1]

Bu, ilk hamleyi iki kez azaltarak 2 hareket gerektirir.

Yüzlerce sayının çok daha büyük dizileri göz önüne alındığında, bunu bulmanın en iyi yolunu bulamıyorum.

Başlangıçta yuvarlatılmış ortalama sayıyı hesaplamaya çalıştım (toplamın uzunluğa bölünmesi) ve daha sonra bunları hesaplanan ortalamaya düşürdüm, ancak yukarıdaki örnek 2 yerine 4 hareket gerektiren bunu kırdı.

Sanırım anlayabilirim:

  1. Ortalama,
  2. Mod,
  3. Ortanca

ve minimum mesafeyi seçerek her birinin düzenleme mesafesini alın. Ancak, bunun her durumda doğru olacağından emin değilim. Nasıl bilebilirim?


Etki alanı sınırlıysa, min. Maks. Aksi takdirde modu veya medyanı kullanmayı deneyebilirsiniz.
Bartosz Przybylski

Teşekkürler @Bartek. Yüzlerce veya binlerce rakamla uğraşırken tüm olasılıkları denemek çok verimsiz görünüyor. Modu / medyanı kontrol edeceğim. Ancak bunların her durumda sonuç üreteceğinden eminler mi? Bu benim asıl sorum. Belirli, verimli bir algoritma arıyorum.
dthree

Sayının sayı kümesinde olması gerekiyor mu, yoksa herhangi bir tam sayı olabilir mi?
TCSGrad

@TCSGrad Herhangi bir tamsayı olabilir, ama belli ki min ve max sayıları arasında bir tane seçmek istersiniz. Bu durumda, 1, 2 veya 3.
14'te

Yanıtlar:


10

Cevap medyan almaktır. Medyanın özelliklerinden biri, her bir elemente L1 mesafesini en aza indirmesidir . (Wikipedia makalesini anlamak için, orijinal sayı diziniz üzerindeki eşit dağılımın olasılık dağılımını alın).

Sorunu çözen algoritma (başlangıçta dc2 tarafından yazılmıştır ):

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

Evet, başardı. Bunun nasıl çalıştığı komik. Medyan bunu yapacak gibi gözükmüyor, ama hey. Çok teşekkürler.
dthree

1
Bir kanıt için cevabımı görün.
Yuval Filmus

@ dc2: "Deneyerek" "emin olamazsınız".
Raphael

1
Sadece şunu not edin: ortanca O (n) zamanını hesaplayabilirsiniz
Bartosz Przybylski

1
@ Raphael OP'nin kodunu OP'ye referans olmadan başka bir yanıta dahil etmek uygun mudur?
thefourtheye

10

TCSGrad bahseder gibi, tamsayılar listesi verildi , sen tamsayı aradığınız m minimize Í ( m ) = n Σ i = 1 | m - x i | . Δ ( m + 1 ) - δ ( m ) ' nin hesaplanması öğreticidir : δ ( m + 1 ) - δ ( m ) =x1,...,xnm

δ(m)=Σben=1n|m-xben|.
δ(m+1)-δ(m) Şöylemgider-için+, miktarδ(m+1)-δ(m)
δ(m+1)-δ(m)=Σben=1n{+1mxben-1m<xben=#{ben:mxben}-#{ben:m<xben}.
m-+δ(m+1)-δ(m)gider için n . Ayrıca, değerleri yalnızca x 1 , , x n noktalarında değiştirir . Optimum m değerinin δ ( m + 1 ) - δ ( m ) 0 olduğu minimum nokta olup olmadığını kontrol etmek zor değildir . Bu minimum nokta x i'den biridir , bu nedenle düzenleme mesafesi min ( δ ( x 1 ) , , δ ( x-nnx1,...,xnmδ(m+1)-δ(m)0xben .min(δ(x1),...,δ(xn))

xbennmxbenδ(m+1)-δ(m)=1δ(m)-δ(m-1)=-1mnxbenδxben


Bunu kaçırmış olabilirsiniz, ancak bu cevap (neredeyse) medyanın en uygun seçim olduğunu kanıtlıyor .
Yuval Filmus

1
cevabınız mükemmeldi ve ben bunu iptal ettim. Ne yazık ki benim için, bilimsel gösterimlerde o kadar iyi tecrübeli olmadığım için biraz fazla mükemmel, çoğunu işlenmiş garble olarak bırakıyorum. Bu benim sorunum, senin değil.
dthree

5

Sorun bir LP problemi olarak formüle edilebilir:

n[bir1,bir2...birn]

minΣ|birben-x|

x

xx

DÜZENLEME : Yorumlarda belirtildiği gibi, amaç işlevi mutlak farklılıklar üzerinden toplanmalıdır. Standart bir LP'ye dönüştürmek için LP'yi şu şekilde yeniden yazabiliriz:

minΣbirben'

tabi:

birben'birben-x ben
birben'birben-x ben
birben',x'0 ben

birben'=|birben-x| benx


Bunu doğru anlarsam, örneğimde, x 1 - 3 olur ve bu nedenle 1, 2 ve 3 düzenleme mesafesini bulurdum ve sonra bir dakikayı yapar mıyım?
dthree

xx

Kısıtlamalar neden gerekli?
Raphael
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.