Algorithme pour faire correspondre les nombres avec un nombre minimum de coups

11

C'est une sorte de question de distance de montage, et c'est très simple. Je suis tout simplement mort cérébrale sur ce sujet et je ne peux pas le comprendre jusqu'à présent.


Étant donné une série de nombres, par exemple

[3, 1, 1, 1]

Comment transformer le plus efficacement tous les nombres en un même nombre, avec le nombre minimum de "coups"? Par «déplacer», on entend ajouter ou supprimer un numéro.

Dans l'exemple ci-dessus, les mouvements les plus efficaces seraient:

[1, 1, 1, 1]

Cela nécessiterait 2 mouvements, réduisant le premier nombre deux fois.

Je ne peux pas trouver la meilleure façon de le savoir, étant donné des tableaux beaucoup plus grands de centaines de nombres.

J'ai à l'origine essayé de calculer le nombre moyen arrondi (somme de tous divisée par la longueur), puis de les réduire à la moyenne calculée, mais l'exemple ci-dessus a cassé cela, nécessitant 4 mouvements au lieu de 2.

Je suppose que je pourrais comprendre:

  1. La moyenne,
  2. La mode,
  3. La médiane

et obtenez la distance d'édition de chacun d'eux, en choisissant la distance minimale. Cependant, je ne suis pas sûr que ce serait correct dans chaque cas. Comment puis-je savoir?

dthree
la source
Si le domaine est limité, vous pouvez essayer toutes les possibilités de min à max. Sinon, vous pouvez essayer d'utiliser le mode ou la médiane.
Bartosz Przybylski
Merci @Bartek. Il semble qu'essayer toutes les possibilités serait extrêmement inefficace s'il s'agissait de centaines ou de milliers de chiffres. Je vais vérifier le mode / médiane. Mais sont-ils certains de produire des résultats dans tous les cas? Voilà ma principale question. Je recherche un algorithme certain et efficace.
3
Le nombre doit-il être dans l'ensemble des nombres, ou peut-il être un entier?
TCSGrad
@TCSGrad Il peut s'agir de n'importe quel entier, mais vous voudrez évidemment en choisir un qui se situe entre le nombre min et max. Dans ce cas, soit 1, 2 ou 3.
dthree

Réponses:

10

La réponse est de prendre la médiane. L'une des propriétés de la médiane est qu'elle minimise la distance L1 à chaque élément. (Pour donner un sens à l'article Wikipedia, prenez la distribution de probabilité comme étant la distribution uniforme sur votre série de nombres d'origine).

Voici l'algorithme qui résout le problème (écrit à l'origine par 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
la source
Ouais, ça l'a fait. C'est drôle comment ça marche. Il ne semble pas que la médiane le ferait, mais bon. Merci beaucoup.
3
1
Voir ma réponse pour une preuve.
Yuval Filmus
@ dc2: Vous ne pouvez pas "vous assurer" en "l'essayant".
Raphael
1
Juste à noter: vous pouvez calculer le temps O (n) médian
Bartosz Przybylski
1
@Raphael Est-il correct d'inclure le code OP dans une autre réponse, sans référence à OP?
thefourtheye
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))

Supposons en outre que tous les sont distincts et que est impair. Soit la médiane du . Alors tandis que , et donc est l'optimum unique. Si est pair, un calcul similaire montre que nous pouvons choisir n'importe quel point de l'intervalle reliant les médianes. Un raisonnement similaire mais plus élaboré montre que toute médiane est optimale même lorsque les ne sont pas distincts. Il n'est donc pas nécessaire de calculer sur tous les .xinmxiδ(m+1)δ(m)=1δ(m)δ(m1)=1mnxiδxi

Yuval Filmus
la source
Vous l'avez peut-être manqué, mais cette réponse prouve (presque) que la médiane est le choix optimal.
Yuval Filmus
1
votre réponse était excellente et je l'ai votée positivement. Malheureusement pour moi, un peu trop excellent car je ne suis pas très bien versé dans la notation scientifique, laissant la plupart d'entre eux comme brouillés. C'est mon problème, pas le vôtre.
dthree
5

Le problème peut être formulé comme un problème LP:

Étant donné un ensemble de nombres , résolvez le LP suivant:n[a1,a2...an]

min|aix|

(Suppression des contraintes sur , qui n'étaient pas nécessaires comme l'a souligné Raphael)x

Une fois le LP résolu, vous obtiendrez une valeur de correspondant à la solution. Si est un entier, vous avez terminé - sinon, arrondissez-le à l'entier le plus proche.xx

EDIT : Comme indiqué dans les commentaires, la fonction objectif doit être la somme des différences absolues. Afin de le reconvertir en LP standard, nous pouvons réécrire le LP comme:

minai

sujet à:

a ia i - x i a i , x 0 i

aiaix i
aiaix i
ai,x0 i

A la solution optimale, , et nous pouvons obtenir la valeur de partir de la solution.xai=|aix| ix

TCSGrad
la source
Donc, si je comprends bien, dans mon exemple, x serait 1 - 3, et donc je trouverais la distance d'édition de 1, 2 et 3, puis ferais une minute à ce sujet?
3
@ dc2: Cela minimiserait la somme des distances entre chaque nombre et , où est le nombre convergent. Les contraintes garantissent que le LP se termine rapidement et ne recherche pas tous les entiers! xxx
TCSGrad
Pourquoi les contraintes sont-elles nécessaires?
Raphael