Exercices Ch7.mcw

publicité
EXERCICES SUR LA TECHNIQUE DIVISER POUR RÉGNER
Chapitre 7
ÉNONCÉS
Exercice 1
(a) Présentez l’approche Diviser pour régner.
(b) Donnez deux conditions fort souhaitables pour que l’approche Diviser pour régner soit efficace.
(c) Donnez deux domaines d’application de l’approche Diviser pour régner.
Exercice 2
Vous décidez d’utiliser la technique diviser pour régner pour résoudre un certain type de problème.
Pour n ≥4, vous savez que vous pouvez obtenir la solution à un exemplaire de taille n en résolvant a
sous-exemplaires de taille n/4. Le temps requis pour la décomposition de l’exemplaire original en a
n2
sous-exemplaires est dans Θ(logn) et le temps requis pour la recombinaison des sous-solutions est
dans Θ(n2). Supposez pour simplifier que n est une puissance de 4.
a)
Donnez l’équation de récurrence asymptotique exprimant le temps d’exécution t(n) de cet
algorithme en fonction de la taille n de l’exemplaire.
b)
Donnez l’ordre exact de t(n), sous la forme la plus simple possible, (i) lorsque a = 8; (ii) lorsque
a = 16; (iii) lorsque a = 32. Aucune preuve n’est requise. Prière de ne pas réinventer la roue!
c)
Les réponses obtenues en b) s’appliquent-elles toujours si n n’est pas une puissance de 4?
Justifiez brièvement votre réponse.
Exercice 3
Un algorithme A est conçu en appliquant le principe général de la technique “diviser pour régner”.
Pour résoudre de petits exemplaires de taille n ≤ n0, il utilise un algorithme Adhoc qui est dans O(n3).
n
Autrement, il décompose l’exemplaire de taille n en k sous-exemplaires de taille k , et les étapes de
décomposition en sous-exemplaires et de combinaison des solutions intermédiaires demandent un
temps dans O(n). Analysez cet algorithme et donnez son efficacité en notation O, de façon aussi
simple que possible. Explicitez vos calculs (vous pouvez supposer que n = km et que n0 = km0).
Exercice 4
Soit un tableau T [1..n] de n entiers distincts, décrivez de manière précise un algorithme retournant
l’indice du minimum des éléments de T, basé sur la technique “diviser pour régner”.
Analyse d’Algorithmes 2000
EXERCICES SUR LA TECHNIQUE DIVISER POUR RÉGNER
1
Exercice 5 (ancien problème 4.11.3)
Soit T[1..n] un tableau de n éléments. Il est facile de déterminer le plus grand élément de T en
faisant exactement n–1 comparaisons entre éléments:
Max ← T[1] ; Ind ← 1
POUR i ← 2 JUSQU'À n faire
SI Max < T[i] ALORS Max ← T[i] ; Ind ← i FINSI
FIN POUR.
Seules les comparaisons entre éléments sont comptées ici, ce qui exclut les comparaisons implicites
dans le contrôle de la boucle POUR. On pourrait subséquemment déterminer le plus petit élément de T
en n–2 comparaisons supplémentaires:
T[Ind] ← T[1] {T[Ind] est le maximum, donc peut être remplacé par T[1]}
Min ← T[2]
POUR i ← 3 JUSQU'À n faire
SI Min > T[i] ALORS Min ← T[i] FINSI
FIN POUR.
Cela donne au total 2n–3 comparaisons.
1º Trouvez un algorithme A basé sur la technique DPR capable de déterminer le plus petit et le
plus grand éléments d'un tableau de n éléments en faisant moins de 2n–3 comparaisons entre
éléments. Vous pouvez supposer que n est une puissance de deux (cependant votre algorithme doit
fonctionner pour tout n ≥ 1). Quel est le nombre exact de comparaisons que votre algorithme requiert?
2º Dans votre algorithme A, beaucoup de temps est perdu dans la gestion des appels récursifs.
Pouvez-vous imaginer un algorithme itératif B faisant le même nombre de comparaisons?
Exercice 6 (problème 7.12 p.252)
Soit T[1..n] un tableau d’entiers distincts triés par valeurs croissantes; certains peuvent être négatifs.
1º Donnez un algorithme qui retourne un indice i de T tel que T[i] = i, en supposant qu’un tel indice
existe. Votre algorithme devrait mettre en pire cas un temps dans O(logn).
2º Justifiez très brièvement le temps mis par votre algorithme (quelques lignes).
Exercice 7
L’algorithme linéaire pour trouver la médiane (section 7.5) permet de faire fonctionner le tri de Hoare
(quicksort) en un temps dans O (n logn) en pire cas.
a) La phrase précédente est-elle vraie ou fausse ? Justifiez brièvement. Vous pouvez supposer, pour
simplifier, que tous les éléments du tableau sont distincts.
b) Est-ce une bonne idée ? Pourquoi ou pourquoi pas ?
2
EXERCICES SUR LA TECHNIQUE DIVISER POUR RÉGNER
R. Lelouche ©2000
Exercice 8
Cet exercice vise à déterminer le seuil n0 à partir duquel le tri par fusion (section 4.4) devrait cesser de
s’appeler récursivement. Notez que les chiffres ci-dessous sont fictifs et qu’ils ont été choisis dans le
but de faciliter les calculs (pas de fraction, etc.).
Considérez l’algorithme suivant:
PROCEDURE TriFusion (T[1..n])
SI n ≤ n0 ALORS
TriQuad (T)
SINON
U ← les n/2 premiers éléments de T
V ← les n/2 autres éléments de T
TriFusion (U); TriFusion (V)
Fusion (T, U, V)
FIN TriFusion.
où :
• TriQuad (T) est un tri quadratique prenant un temps moyen an2 + bn + c pour trier n éléments,
• Fusion (T, U, V) fusionne deux séquences triées dont la somme des longueurs est n en un temps
moyen dn + e.
Pour simplifier, on suppose que les temps moyens pris par TriQuad et Fusion dépendent uniquement
de n et ne dépendent pas de l’ordre relatif des éléments dans les tableaux. Grâce à votre horloge (dont
la précision est supposée parfaite !), vous avez déterminé que TriQuad prend en moyenne 25, 109 et
469 microsecondes pour trier 4, 8 et 16 éléments respectivement. De même, la partie non récursive de
TriFusion (c'est-à-dire tout sauf les appels récursifs, lorsque n > n0) prend en moyenne 131 et 251
microsecondes pour traiter 8 et 16 éléments respectivement.
a) Déterminez un seuil n0 à peu près optimal (minimisant approximativement le temps moyen) pour
cette implantation du tri par fusion. Pour simplifier, approximez n/2 et n/2 par n/2.
b) Sachant que la solution générale de l’équation de récurrence
T (n) ∈
t(n)
{ T (n2 ) + T (  n2 ) + β n + γ
si n ≤ n 0
si n > n 0
est
n t(n 0 ) + γ
n
T(n) = βn lgn +
n – γ pour n ≥ n0 lorsque n est une puissance de 2
n
0
0
0
lequel des trois paramètres suivants a le plus d’influence sur le temps requis par le tri par fusion
lorsque le nombre d’éléments à trier est très très grand:
- le seuil bien choisi,
- l’efficacité de l’algorithme ad hoc (TriQuad), ou
- l’efficacité de la partie non récursive de l’algorithme ?
Justifiez votre réponse.
Analyse d’Algorithmes 2000
EXERCICES SUR LA TECHNIQUE DIVISER POUR RÉGNER
3
Exercice 9
Un polynôme de degré n, tel que an xn + an–1 xn–1 + ... + a1 x + a0, est représenté par le tableau
P[0..n] de ses coefficients, c’est-à-dire que P[i] = a i. Supposez que vous disposiez déjà d’un
algorithme capable de multiplier symboliquement deux polynômes de degré au plus m en un temps
dans O(m logm). Soient x1, x2, ..., xn des entiers quelconques. Esquissez un algorithme efficace,
basé sur la technique diviser pour régner, capable de calculer les coefficients du polynôme produit
(x – x 1 ) (x – x 2 ) ... (x – x n ). Par exemple, si n = 3, x 1 = 2, x 2 = –1, et x 3 = 1, il faut retourner
le tableau [2, –1, –2, 1] correspondant au polynôme (x – 2) (x + 1) (x – 1) = x3 – 2x2 – x + 2.
En fonction de n, exprimez le temps pris par votre algorithme sous la forme d’une équation de récurrence asymptotique. Résolvez cette récurrence en notation O lorsque n est une puissance de 2.
Exercice 10
Supposons que vous ayez un problème à résoudre et que vous décidiez d’utiliser une méthode diviser
pour régner telle que la solution d’un problème de taille 3n demande la solution de 9 sous-problèmes
du même type, mais de taille n. Supposons de plus que le temps requis pour la séparation du
problème original en sous-problèmes et pour la combinaison des sous-solutions ainsi obtenues soit de
Θ(n2) opérations. Supposez pour simplifier que cet algorithme ne sera utilisé que sur des problèmes
dont la taille est une puissance exacte de 3.
i) Donnez l’équation de récurrence exprimant le temps d’exécution de cet algorithme en fonction de la
taille du problème à traiter.
ii) Exprimez en notation Θ le temps requis par cet algorithme sur un problème de taille n. (Preuves
non requises. Ne ré-inventez pas la roue!)
iii) Quelle aurait été la réponse à (ii) s’il avait fallu résoudre 10 sous-problèmes plutôt que 9 ?
iv) Idem avec 8 sous-problèmes.
Exercice 11 (ancien problème 4.8.5)
Démontrez que h(A) = lgA + le nombre de “1” dans la représentation binaire de A.
Exercice 12
0 1
Considérez la matrice F = 1 1 . Soient i et j deux entiers quelconques. Que vaut le produit du
vecteur (i j) par la matrice F? Que se passe-t-il si i et j sont deux termes consécutifs de la suite de
Fibonacci ? En utilisant la matrice F, donnez une équation pour le ne terme de la suite de Fibonacci.
Déduisez-en un algorithme de type diviser pour régner pour calculer ce ne terme. Donnez l’ordre exact
du temps d’exécution de votre algorithme, sans tenir compte de la taille des opérandes (vous pouvez
supposer, par exemple, que tous les calculs se font modulo 1000).
( )
4
EXERCICES SUR LA TECHNIQUE DIVISER POUR RÉGNER
R. Lelouche ©2000
Exercice 13
Concevoir un algorithme basé sur la technique diviser pour régner pour résoudre le problème suivant:
Soit T[1 .. n] un vecteur d’entiers non nécessairement distincts. Retourner la liste
{ (u, nu) | u est un élément de T,
nu désigne le nombre d’occurrences de u dans T,
les couples (u, nu) sont ordonnés en ordre croissant de u }.
Exemple: soit T[1 .. 6] = [12, 3, 12, 4, 3, 12]. La liste solution est alors
{ (3, 2), (4, 1), (12, 3) }
signifiant: “3” apparaît 2 fois, “4” apparaît 1 fois, et “12” apparaît 3 fois.
Note: L’entête de la fonction vous est donné:
Fonction DPR(T[1 .. n]): ensemble;
Exercice 14 (élément majoritaire, ancien problème 4.11.5)
Soit T[1 .. n] un tableau de n éléments. Un élément x est dit majoritaire dans T si le nombre
d’éléments égaux à x dans T est supérieur à n/2. Le tableau T est dit majoritaire s’il contient un (et
donc un seul) élément majoritaire. Donnez un algorithme capable de déterminer si un tableau T[1.. n]
est majoritaire et d’en déterminer l’élément majoritaire, s’il y a lieu, en un temps linéaire.
Exercice 15
Considérons le problème de la multiplication par lui-même d’un entier de n chiffres, où n peut être
arbitrairement élevé. Décrivez un algorithme efficace pour résoudre ce problème à l’aide de la
technique diviser pour régner. En supposant pour simplifier que n est une puissance de 2, exprimez
sous forme d’équation de récurrence la complexité de cet algorithme.
Note. - Nous avons vu en classe un algorithme basé sur la technique diviser pour régner pour
multiplier deux entiers quelconques de n chiffres en un temps dans O(nlg3). Vous pouvez supposer
que cet algorithme est disponible si vous devez multiplier deux entiers différents.
Analyse d’Algorithmes 2000
EXERCICES SUR LA TECHNIQUE DIVISER POUR RÉGNER
5
EXERCICES SUR LA TECHNIQUE DIVISER POUR RÉGNER
Chapitre 7
SOLUTIONS
Exercice 1 (voir cours)
Exercice 2
a)
t (n) ∈ a t (n/4) + Θ (n2/logn) + Θ (n2)
∈ a t (n/4) + Θ (n2)
b)
On utilise le résultat de l’exemple 4.7.13 (anc. problème 2.3.6) (p. 133 du livre ou transparents
chapitre 4, p. 35) avec n0 = b = 4 et k = 2. Lorsque n est une puissance de b = 4, on a:
Θ (n2)
pour a = 8 (cas particulier de a < bk)
pour a = bk = 16
t (n) ∈ Θ (n2 logn)
pour a = 32 (cas particulier de a > bk).
Θ (nlog432) = Θ (n5/2)
c)
Oui. En effet, t(n) est éventuellement non décroissante et les fonctions, n2, n2logn et n5/2 sont 4harmonieuses (très facile à vérifier). Donc, par la règle de l’harmonie (nouveau livre p. 90, ou
ancien problème 2.1.20), le résultat de b) s’applique sans condition sur la valeur de n (que ce soit
ou non une puissance de 4).
Exercice 3
Appelons t(n) le temps mis par l’algorithme A pour résoudre un exemplaire de taille n. Il vient:
t(n) ∈
{
O(n3)
si n ≤ n 0 (algorithme Adhoc)
n
k t (   ) + O(n) sinon
(algorithme récursif)
k
Posons n = km et n0 = km0. L’équation ci-dessus se réécrit:
t(km ) ∈
3m )
si m ≤ m 0
{ O(k
k t ( k m –1 ) + O(k m ) sinon
(algorithme Adhoc)
(algorithme récursif)
Ainsi, d’après la définition de l’ordre, pour m > m0, il existe b et c réels positifs tels que
t(k m ) ≤
{ kc tk(3mk m – 1 ) + b k m
si m ≤ m 0 (algorithme Adhoc)
sinon
(algorithme récursif)
Posons t(km) = tm. On a, en nous intéressant aux égalités, que nous réécrivons
6
EXERCICES SUR LA TECHNIQUE DIVISER POUR RÉGNER
R. Lelouche ©2000
3m
{ ttmm =–c kk t m – 1
= b
km
si m ≤ m 0 (algorithme Adhoc)
sinon
(algorithme récursif)
L’équation du bas est une équation de récurrence de polynôme caractéristique (x–k) (x–k) = (x–
k)2, et dont la solution a la forme générale
tm = t(km) = c1 km + c2 m km
où c1 et c2 sont des constantes réelles à déterminer, d’après les conditions initiales.
(1)
En écrivant que l’équation de récurrence et la forme générale de la solution fournissent la même
expression, on a pour m = m0 (équation du haut) :
tm0 = t(km0) = c k3m0 = c1 km + c2 m0 km
pour m = m0+1 > m0 (équation du bas) :
(2)
tm0+1 = t(km0+1) = k tm0 + b km0+1 = c1 km0+1 + c2 (m0+1) km0+1
(3)
En remplaçant dans (3) tm0 par son expression tirée de la solution générale et en simplifiant, il vient:
tm 0+1 = c1 km0+1 + c2 m0 km0+1 + b km0+1
km0+1
km0+1
d’après la récurrence
km0+1
= c1
+ c2 m 0
+ c2
d’après (1)
L’égalité de ces deux expressions de tm0+1 conduit donc immédiatement à :
c2 = b > 0
La valeur de c1 s’obtient ensuite simplement par report de cette valeur dans (2), et on trouve :
c1 = m0 b – c k2m0
On sait que c2 est positif, parce que b l’est à cause de O(n). En revanche, on ne sait rien du
signe de c1, car cela dépend des valeurs effectives de b, c, k, et m0. Mais cela n’a pas d’importance.
En effet, en revenant à n = km, qui donne m = logkn, et aux inégalités, la solution générale (1) s’écrit:
t(n) ≤ c1 n + c2 n logkn
qui, puisque c2 est positif, suffit à conclure que, lorsque n est une puissance de k
t(n) ∈ O (n logn).
Remarque. Il est intéressant de constater que l’efficacité de l’algorithme ad hoc utilisé pour
résoudre les exemplaires de petite taille n’intervient absolument pas dans l’efficacité globale de
l’algorithme DPR qui s’en déduit. L’énoncé proposait ici un algorithme cubique, mais toute puissance
nα avec α > 1 aurait donné le même résultat: un algorithme en O (n logn) est toujours plus efficace.
En revanche, cela n’aurait certainement pas été le cas si cet algorithme ad hoc avait été lui-même
linéaire (α = 1)1. En effet, l’algorithme DPR, étant au moins dans O (n logn) à cause de sa partie
récursive, n’aurait dans tous les cas rien apporté asymptotiquement, et aurait fort probablement eu une
constante multiplicative supérieure à celle de l’algorithme ad hoc !
1 Une version antérieure de cet exercice donnait pourtant un algorithme ad hoc en O(n). S’agissait-il alors d’un exercice
piège? Plutôt que de vous poser des pièges, j’ai préféré augmenter l’intérêt de l’exercice... J
Analyse d’Algorithmes 2000
EXERCICES SUR LA TECHNIQUE DIVISER POUR RÉGNER
7
Exercice 4
Fonction Min (T[i..j])
SI i = j ALORS Retourner i
SINON
Pivot ← (i+j+1) DIV 2;
Min_Gauche ← Min (T[i..Pivot–1])
Min_Droite ← Min (T[Pivot..j])
SI T[Min_Gauche] < T[Min_Droite]
ALORS RETOURNER Min_Gauche
SINON RETOURNER Min_Droite.
Exercice 5
1º La fonction récursive suivante A = MinMax fournit le plus petit élément (u) et le plus grand
élément (v) du tableau T. Elle utilise la technique diviser pour régner.
FONCTION MinMax (T [1 .. n]): (reel, reel)
{On suppose que n ≥ 1}
SI n > 2 ALORS
s ← n DIV 2
(u1, v1) ← MinMax (T [1 .. s])
(u2, v2) ← MinMax (T [s+1 .. n])
RETOURNER (MIN (u1, u2), MAX (v1, v2))
SI n = 1 ALORS RETOURNER (T [1], T [1])
{Assert: n = 2}
SI T [1] < T [2] ALORS RETOURNER (T [1], T [2])
SINON {T [1] ≥ T [2]} RETOURNER (T [2], T [1]).
FIN MinMax.
Soit t (n) le nombre de comparaisons entre éléments effectuées par MinMax. Les parties d’énoncés
“MIN (u1, u2)”, “MAX (v1, v2)”, et “T [1] < T [2]” effectuent chacune une comparaison. Pour ce qui
est des appels récursifs à MinMax, supposons que n est une puissance de 2. Alors:
t (2) = 1
pour n = 2
t (n) = 2 t(n/2) + 2
pour n ≥ 2.
Il est ainsi clair (voir exemple 4.7.13 du livre ou des transparents) que t (n) ∈ Θ(n).
Travaillons par induction constructive et prenons l’hypothèse d’induction HI(n) : t (n) = an + b.
Supposons que HI(k) est vérifié pour tout k < n, k puissance de 2. Alors:
t (n) = 2 t (n/2) + 2 = 2 a (n/2) + 2b + 2 = an + 2b + 2.
et HI (n) peut être vérifié ∀ k si et seulement si b = 2b + 2, donc si l’on prend b = –2.
Comme HI(2) doit aussi être vérifié, il faut 1 = t(2) = 2a – 2, qui donne a = 3/2. Donc
3n
t (n) = 2 – 2
lorsque n est une puissance de 2. Évidemment, c’est environ 25% de moins que 2n – 3 (constante
multiplicative 3/2 au lieu de 2).
2º Dans la fonction ci-dessus, beaucoup de temps est gaspillé dans la gestion des appels
récursifs. La version itérative du même algorithme (souvenez-vous qu’il est toujours possible d’écrire
systématiquement une verion itérative d’un algorithme récursif quelconque) donnera évidemment au
même nombre de comparaisons. Cependant, on peut écrire directement une fonction B = MinMaxIter
qui fait le même nombre de comparaisons lorsque n est une puissance de 2:
8
EXERCICES SUR LA TECHNIQUE DIVISER POUR RÉGNER
R. Lelouche ©2000
FONCTION MinMaxIter (T [1..n])
{On suppose que n ≥ 1}
{Initialisation de la boucle}
SI n est impair ALORS
(u, v) ← (T [n], T [n])
SINON {n est pair} SI T [n–1] < T [n] ALORS
(u, v) ← (T [n–1], T [n])
SINON {n est pair et T [n–1] ≥ T [n]}
(u, v) ← (T [n], T [n–1])
s ← (n–1) DIV 2
{Boucle proprement dite}
POUR i ← 1 JUSQU’À s FAIRE
SI T [i] < T [i+s] ALORS
u ← MIN (T [i], u)
v ← MAX (T [i+s], v)
SINON {T [i] ≥ T [i+s]}
u ← MIN (T [i+s], u)
v ← MAX (T [i], v)
RETOURNER (u, v)
FIN MinMaxIter.
À chaque tour de la boucle POUR , B effectue trois comparaisons entre éléments: une pour la
comparaison entre T [i] et T [i+s], une pour affecter u, et une pour affecter v. Il y en a une de plus
(dans l'initialisation) lorsque n est pair. Donc, si n est une puissance de 2,
n–1
n–2
t (n) = 1 + 3  2  = 1 + 3
2
3n
soit
t (n) = 2 – 2
ce qui confirme le résultat annoncé.
Exercice 6 (problème 7.12, non résolu ici)
Exercice 7
a) C’est vrai. Il suffit, à chaque pivotage, de calculer la médiane et de la choisir comme pivot. Les
appels récursifs se feront alors sur des tableaux de tailles n/2 et n/2 – 1. Ainsi le temps requis
par quicksort obéirait à:
t (n) ∈ Θ (n) + t (n/2) + t (n/2 – 1)
d'où t (n) ∈ O (n logn).
b) C’est une très mauvaise idée. En effet, même si le tri de Hoare (quicksort) prend en un temps
dans O (n logn) en pire cas, la constante multiplicative associée à cette version «améliorée» de
l’algorithme est si grande qu’elle conduit à un algorithme pire que le tri de Williams (tri par
monceau ou heapsort) dans tous les cas. Voir le dernier paragraphe, et plus spécifiquement la
dernière ligne, de la section 7.4.2 du livre.
Exercice 8
a) La partie non récursive prend un temps de la forme β n + γ. Pour trouver a, b, c, β et γ, il faut
résoudre les systèmes:
Analyse d’Algorithmes 2000
EXERCICES SUR LA TECHNIQUE DIVISER POUR RÉGNER
9
8β + γ = 131
16β + γ = 251
16a + 4b + c = 25
64a + 8b + c = 109
256a + 16b + c = 469
⇓
⇓
8β + γ = 131
8β
= 120
16a + 4b + c = 25
12a + b
= 21
96a
= 192
⇒
a=2
b = –3
β = 15
c=5
La procédure TriFusion prend donc un temps T(n) donné par:
µsec
t(n) = 2n2 – 3n + 5
T(n/2) + T(n/2) + 15n + 11 µsec
γ = 11
si n ≤ n0
si n > n0
Pour un problème de taille n, si on appelle directement TriQuad, il faut un temps moyen t(n). Si
on divise une dernière fois en deux puis on appelle TriQuad au coup suivant, il faut un temps
moyen 2 t(n/2) + 15n + 11.
n0 sera la plus grande valeur de n telle que t(n) ≤ 2t(n/2) + 15n + 11, c’est-à-dire:
2n2 – 3n + 5 –2(2n2/4 – 3n/2 + 5) – 15n –11 = n2 – 15n – 16 = (n + 1) (n – 16) ≤ 0
On choisit donc n0 = 16.
b) Le temps moyen requis sera
T (n) = β n [lgn – lgn0] +
t(n0) + γ
n – γ ∈ β n lgn + Θ (n).
n0
C'est donc la constante β qui a le plus d'influence, c'est-à-dire la partie non récursive de
l'algorithme.
Exercice 9 (non résolu ici)
Exercice 10 (non résolu ici)
Exercice 11 (ancien problème 4.8.5)
La démonstration se fait par induction sur A. L’énoncé est évidemment vrai pour A = 1.
Supposons qu’il soit vrai pour toutes les valeurs inférieures à A. Alors :
a) si A est impair,
lgA = lg(A–1) et A a un “1” de plus que A–1 dans sa représentation binaire. Comme le
résultat tient pour A–1 et que h(A) = 1 + h(A–1), il tient aussi pour A.
b) si A est pair,
lgA = lg(A–1) + 1 et A/2 a le même nombre de “1” que A dans sa représentation binaire.
Comme la propriété tient pour A/2 et que h(A) = 1 + h(A/2), elle tient aussi pour A.
10
EXERCICES SUR LA TECHNIQUE DIVISER POUR RÉGNER
R. Lelouche ©2000
Exercice 12
(i j )
On a
( 01 11 ) = ( j i+j )
et ( fn fn+1 )
( 01 11 ) = ( fn+1 fn+2 )
(fn–1 fn) = (0 1) Fn–1
On voit que
Pour calculer fn, il suffit donc de calculer Fn–1 et de prendre l'élément du coin inférieur droit.
Le problème du calcul de Fk est celui de l'exponentiation (section 4.8). On utilise l'égalité:
Fk =
 si k = 0 (matrice identité)
 F × Fk–1
si k impair, k > 0
k/2
k/2
si k pair, k > 0.
 F ×F
On obtient l'algorithme suivant (version itérative):
FONCTION
Fib (n)
k ← n–1; M ← F; A ← I
TANTQUE k > 0 FAIRE
SI k impair ALORS A ← A × M
M←M×M
k ← k DIV 2
RETOURNER l’élément (2, 2) de A.
FIN Fib.
Ici, le × représente le produit matriciel.
Comme pour l'exponentiation à la section 4.8, cet algorithme prend un temps dans Θ (logn) si on ne
tient pas compte de la taille des opérandes.
Exercice 13
FONCTION DPR (T[1 .. n]): liste;
SI n = 0 ALORS DPR ← Ø
SINON {n > 0}
Soient 2 vecteurs U et V, initialement vides
Soit W un élément quelconque de T, disons T[1]
Compteur ← 0;
POUR i ← 1 à n FAIRE
SI T[i] = W ALORS Compteur ← Compteur + 1;
SINON SI T[i] < W ALORS concaténer T[i] à U
SINON {T[i] > W} concaténer T[i] à V
DPR ← DPR (U) ∪ (W, Compteur) ∪ DPR (V) (où ∪ dénote la juxtaposition)
Fin DPR.
Analyse en pire cas. Cela correspond au cas où :
- tous les éléments sont distincts, car la boucle isole un seul élément ;
- l’instruction de recombinaison donne U ou V vide, ce qui entraîne n–1 appels récursifs en chaîne.
L’algorithme est alors en Ω (n2).
Analyse d’Algorithmes 2000
EXERCICES SUR LA TECHNIQUE DIVISER POUR RÉGNER
11
Analyse en meilleur cas. Cela correspond au cas où tous les éléments sont égaux à W. L’algorithme
retourne alors la liste (W, n) en temps linéaire.
Analyse dans le cas général. Si W est bien placé, les sous-listes U et V devraient être de longueurs
comparables. En particulier, si tous les éléments sont distincts et si à chaque itération U et V ont la
même longueur, le temps global sera dans O (n logn).
Exercice 14 (élément majoritaire, ancien problème 4.11.5)
a) Première approche
PROCÉDURE TrouverMajoritaire (T[1..n], var Major: booléen, var X)
{si le tableau T n’est pas majoritaire, on retrourne faux dans Major;
sinon, on retourne vrai dans Major et l’élément recherché dans X}
SI n est suffisamment petit ALORS {procédure ad-hoc}
- trier le tableau T en ordre croissant
- rechercher l’élément majoritaire (s’il y a lieu) en parcourant séquentiellement T.
SINON {n est grand ⇒ diviser pour régner}
p ← un élément quelconque de T[1 .. n]
u ← # {i ∈ [1 .. n] | T[i] < p}
v ← # {i ∈ [1 .. n] | T[i] ≤ p}
SI u > n/2 ALORS {les éléments inférieurs à p sont les plus nombreux}
soit le tableau U[1 .. u],
U ← les éléments de T inférieurs à p
TrouverMajoritaire (U, major, X)
SI x ≤ n/2 ALORS Major ← faux
SINON si v < n/2 alors {les éléments supérieurs à p sont les plus nombreux}
soit un tableau V [1 .. (n–v)]
V ← les éléments de T supérieurs à p
TrouverMajoritaire (V, Major, X)
SI x ≤ n/2 ALORS Major ← faux
SINON {ni les éléments < p, ni les éléments > p, ne sont les plus nombreux}
SI v–u > n/2 ALORS Major ← vrai, X ← p
SINON Major ← faux
FIN TrouverMajoritaire.
b) Une seconde approche consiste à calculer la médiane m de T[1 .. n] en temps linéaire et à vérifier si
m est un élément majoritaire.
En effet, si m est la médiane de T, cela signifie (définition de la médiane) que
# {i∈ [i .. n] | T [i] < m} < n/2 et # {i∈ [i .. n] | T [i] > m} ≤ n/2
1er cas: m < X et X est un élément majoritaire
Alors # {i | T[i] > m } ≤ n/2 ⇒ # {i | T [i] ≥ X} < n/2, ce qui contredit que X soit majoritaire.
2me cas: m > X et X est un élément majoritaire
Alors # {i | T[i] < m} < n/2 ⇒ # {i | T [i] ≤ X} < n/2, ce qui contredit que X soit majoritaire.
Ainsi, s’il existe un élément majoritaire X, alors X est aussi la médiane de T.
12
EXERCICES SUR LA TECHNIQUE DIVISER POUR RÉGNER
R. Lelouche ©2000
Exercice 15
Soit C l’entier de n chiffres à multiplier par lui-même, avec n assez grand pour qu’il vaille la peine
d’utiliser la technique diviser pour régner. L’entier C est composé de deux moitiés A et B de n/2
chiffres chacune. Alors
C = A × 10n/2 + B
et par suite
C2 = A2 × 10n + 2 × A × B × 10n/2 + B2
D’où l’algorithme (le signe • représente la concaténation):
Fonction CarréDPR (C: suite de n chiffres): suite de 2n chiffres.
{Retourne la suite de 2n chiffres dont la valeur est le carré de l’entier représenté par C}
Si Petit (n) alors
Retourner C*C
{fonction ad-hoc, temps unitaire}
sinon {n n’est pas petit: diviser pour régner}
Cg ← moitié gauche de C
{de longueur n/2 chiffres, de valeur A}
Cd ← moitié droite de C
{de longueur n/2 chiffres, de valeur B}
AB ← produit de Cg par Cd par l’algorithme vu en classe
{longueur n, valeur AB}
{longueur n, valeur A2}
A2 ← CarréDPR (Cg) {appel récursif}
{longueur n, valeur B2}
B2 ← CarréDPR (Cd) {appel récursif}
{longueur 2n, valeur A2 × 10n}
PartieForte ← A2 • n zéros
PartieMoyenne ← (AB + AB) • n/2 zéros {longueur 3n/2, valeur 2 × A × B × 10n/2}
{longueur n, valeur B2}
PartieFaible ← B2
Résultat ← Somme (PartieForte, PartieMoyenne, PartieFaible) {long. 2n, valeur C2}
Retourner Résultat
{longueur 2n, valeur C2}
fin si
Fin CarréDPR.
Le temps mis par cet algorithme CarréDPR pour traiter un exemplaire de taille n se calcule
comme suit:
 a n + b
t(n) = 
 e n 2
( n2) lg3 + c t (  n2 ) + d t (  n2 )
si non Petit (n)
si Petit (n)
où:
- le terme a n correspond aux parties non récursives linéaires de la branche SINON l’algorithme;
- le terme b nlg3 correspond au calcul de AB par l’algorithme récursif vu en classe;
n
n
- les deux termes c t( ) + d t( ) correspondent aux deux appels récursifs à CarréDPR;
2
2
- le dernier terme e n2 correspond à la procédure standard de calcul du carré;
- les constantes a, b, c, d, e dépendent de l’implantation.
Analyse d’Algorithmes 2000
EXERCICES SUR LA TECHNIQUE DIVISER POUR RÉGNER
13
Téléchargement