Algorytm dopasowywania liczb przy minimalnej liczbie ruchów


11

Jest to rodzaj pytania do edycji i jest bardzo łatwe. Jestem po prostu dość martwy w tym temacie i jak dotąd nie mogę tego rozgryźć.


Biorąc pod uwagę szereg liczb, np

[3, 1, 1, 1]

Jak najskuteczniej przekształcić wszystkie liczby w tę samą liczbę przy minimalnej liczbie „ruchów”? Przez „przeniesienie” rozumie się dodanie lub usunięcie jednego z numeru.

W powyższym przykładzie najbardziej wydajnymi ruchami byłyby:

[1, 1, 1, 1]

Wymagałoby to 2 ruchów, dwukrotnie zmniejszając pierwszą liczbę.

Nie mogę znaleźć najlepszego sposobu, aby się tego dowiedzieć, biorąc pod uwagę znacznie większe tablice setek liczb.

Początkowo próbowałem obliczyć zaokrągloną średnią liczbę (sumę wszystkich podzieloną przez długość), a następnie zredukować ją do obliczonej średniej, ale powyższy przykład złamał to, wymagając 4 ruchów zamiast 2.

Myślę, że mógłbym wymyślić:

  1. Średnia,
  2. Tryb,
  3. Mediana

i uzyskaj odległość edycji każdego z nich, wybierając minimalną odległość. Nie jestem jednak pewien, czy byłoby to poprawne w każdym przypadku. Skąd mam wiedzieć?


Jeśli domena jest ograniczona, możesz wypróbować wszystkie możliwości od min do maks. W przeciwnym razie możesz spróbować użyć trybu lub mediany.
Bartosz Przybylski

Dzięki @Bartek. Wygląda na to, że wypróbowanie wszystkich możliwości byłoby niezwykle nieefektywne, gdybyśmy mieli do czynienia z setkami lub tysiącami liczb. Sprawdzę tryb / medianę. Ale czy na pewno przyniosą rezultaty w każdym przypadku? To moje główne pytanie. Szukam pewnego, wydajnego algorytmu.
3

Czy liczba musi znajdować się w zestawie liczb, czy może być liczbą całkowitą?
TCSGrad

@TCSGrad Może to być dowolna liczba całkowita, ale oczywiście chcesz wybrać między liczbą minimalną i maksymalną. W tym przypadku 1, 2 lub 3
3

Odpowiedzi:


10

Odpowiedź brzmi: wziąć medianę. Jedną z właściwości mediany jest to, że minimalizuje odległość L1 do każdego elementu. (Aby zrozumieć sens artykułu z Wikipedii, weź rozkład prawdopodobieństwa za równomierny rozkład w stosunku do oryginalnej serii liczb).

To jest algorytm, który rozwiązuje problem (pierwotnie napisany przez 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

Tak, to zrobiło. Zabawne, jak to działa. Nie wydaje się, żeby mediana to zrobiłaby, ale hej. Wielkie dzięki.
3

1
Zobacz moją odpowiedź na dowód.
Yuval Filmus

@ dc2: Nie możesz „upewnić się”, „wypróbowując”.
Raphael

1
Uwaga: można obliczyć medianę czasu O (n)
Bartosz Przybylski

1
@Raphael Czy to możliwe, aby dołączyć kod OP do innej odpowiedzi, bez odniesienia do OP?
czwórka

10

Jak wspomina TCSGrad, biorąc pod uwagę listę liczb całkowitych , szukasz liczby całkowitej m minimalizującej δ ( m ) = n i = 1 | m - x i | . Pouczające jest obliczenie δ ( m + 1 ) - δ ( m ) : δ ( m + 1 ) - δ ( m ) =x1,,xnm

δ(m)=ja=1n|m-xja|.
δ(m+1)-δ(m) Gdymzmienia się z-na+, ilośćδ(m+1)-δ(m)
δ(m+1)-δ(m)=ja=1n{+1mxja-1m<xja=#{ja:mxja}-#{ja:m<xja}.
m-+δ(m+1)-δ(m)idzie od do n . Ponadto przełącza wartości tylko w punktach x 1 , , x n . Nie jest trudno sprawdzić, czy optymalna wartość m jest minimalnym punktem, w którym δ ( m + 1 ) - δ ( m ) 0 . Ten minimalny punkt jest jednym z x i , więc odległość edycji wynosi min ( δ ( x 1 ) , , δ ( x-nnx1,,xnmδ(m+1)-δ(m)0xja .min(δ(x1),,δ(xn))

xjanmxjaδ(m+1)-δ(m)=1δ(m)-δ(m-1)=-1mnxjaδxja


Być może tego nie zauważyłeś, ale ta odpowiedź (prawie) dowodzi, że mediana jest optymalnym wyborem.
Yuval Filmus

1
twoja odpowiedź była doskonała i głosowałem za nią. Na nieszczęście dla mnie, trochę zbyt doskonała, ponieważ nie jestem zbyt dobrze zorientowana w notacji naukowej, pozostawiając większość z niej jako zdezorientowaną. To mój problem, nie twój.
3

5

Problem można sformułować jako problem LP:

n[za1,za2)...zan]

min|zaja-x|

x

xx

EDYCJA : Jak wskazano w komentarzach, funkcją celu powinna być suma nad różnicami bezwzględnymi. Aby przekształcić go z powrotem w standardowy LP, możemy przepisać LP jako:

minzaja

z zastrzeżeniem:

zajazaja-x ja
zajazaja-x ja
zaja,x0 ja

zaja=|zaja-x| jax


Więc jeśli dobrze to zrozumiem, w moim przykładzie x będzie wynosić 1 - 3, a więc znajdę odległość edytowania 1, 2 i 3, a następnie zrobię min na tym?
3

xx

Dlaczego ograniczenia są konieczne?
Raphael
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.