Adloun

Diviser pour régner

Cours · informatique (MP2I/MPI), chapitre 15 · MP2I et MPI · le début du chapitre, la suite sur Adloun

Diviser pour régner : un problème est coupé en deux, chaque moitié est résolue, puis les solutions sont fusionnées.

15.1 Trois temps

Le chapitre précédent énumérait ; celui-ci découpe. La méthode se dit en trois temps :

Le gain vient d'un fait arithmétique : diviser la taille par deux à chaque étape ne laisse que étages. Encore faut-il que le troisième temps soit bon marché — c'est là que tout se joue, et c'est ce que la récurrence du chapitre chap:recursivite mesure :

15.2 La dichotomie

Définition 15.1Recherche dichotomique

Chercher dans un tableau trié : on compare à l'élément médian, ce qui élimine la moitié du tableau.


(* Renvoie Some i tel que t.(i) = v, ou None.
   Précondition : t est trié par ordre croissant. *)
let recherche t v =
  let rec aux g d =
    if g > d then None
    else
      let m = g + (d - g) / 2 in
      if t.(m) = v then Some m
      else if t.(m) < v then aux (m + 1) d
      else aux g (m - 1)
  in
  aux 0 (Array.length t - 1)

Ici : un seul sous-problème est résolu, et la combinaison est vide. .

ImportantCe que veut dire
recherche linéairedichotomie
1 00010
1 000 00020
1 000 000 00030

Multiplier la taille par mille n'ajoute que dix comparaisons. C'est le rendement le plus spectaculaire de tout le livre, et il ne coûte qu'une chose : que le tableau soit trié.

15.2.1 La dichotomie là où on ne l'attend pas

Le programme insiste : « on présente un exemple de dichotomie où son recours n'est pas évident : par exemple, la couverture de points de la droite par segments égaux de plus petite longueur ».

Méthode : Dichotomiser sur la RÉPONSE, et non sur les données

Le problème ne parle d'aucun tableau trié. L'idée est ailleurs : on ne cherche pas dans les données, on cherche la valeur de la réponse, et l'on s'appuie sur une propriété de monotonie.

Le problème. points sur une droite, segments de même longueur . Quelle est la plus petite permettant de tout couvrir ?

L'observation décisive. Si une longueur suffit, alors toute longueur suffit aussi. La propriété « suffit » est donc monotone en : fausse jusqu'à un seuil, vraie ensuite. Un seuil dans une suite monotone se cherche par dichotomie.

Le test, glouton et linéaire. Pour une donnée, on couvre au plus vite : le premier segment commence au premier point non couvert, et l'on recommence.


(* Nombre minimal de segments de longueur L couvrant les points triés x. *)
let segments_necessaires x l =
  let n = Array.length x in
  let compte = ref 0 and i = ref 0 in
  while !i < n do
    let debut = x.(!i) in
    incr compte;
    while !i < n && x.(!i) <= debut +. l do incr i done
  done;
  !compte

(* Plus petite longueur permettant de couvrir x avec k segments, à eps près.
   Précondition : x trié, non vide, k >= 1. *)
let plus_petite_longueur x k eps =
  let bas = ref 0.0 and haut = ref (x.(Array.length x - 1) -. x.(0)) in
  while !haut -. !bas > eps do
    let milieu = (!bas +. !haut) /. 2.0 in
    if segments_necessaires x milieu <= k then haut := milieu   (* ça suffit *)
    else bas := milieu                                          (* trop court *)
  done;
  !haut

Complexité. Chaque test est , et la dichotomie divise l'intervalle par deux : .

Exercices du chapitre

La suite du cours · Tous les exercices du chapitre