Académique Documents
Professionnel Documents
Culture Documents
Exercices Ch07 PDF
Exercices Ch07 PDF
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.
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.
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!
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”.
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?
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.
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.
t(n) si n ≤ n 0
T (n) ∈ { T (n2 ) + T ( n2 ) + β n + γ 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
0 n 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 ?
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.
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 ?
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).
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.
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.
Exercice 2
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)
t (n) ∈ Θ (n2 logn) pour a = bk = 16
Θ (nlog432) = Θ (n5/2) pour a = 32 (cas particulier de a > bk).
c) Oui. En effet, t(n) est éventuellement non décroissante et les fonctions, n2, n2logn et n5/2 sont 4-
harmonieuses (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:
Ainsi, d’après la définition de l’ordre, pour m > m0, il existe b et c réels positifs tels que
si m ≤ m 0 (algorithme Adhoc)
t(k m ) ≤ { kc tk(3mk m – 1 ) + b k m sinon (algorithme récursif)
Posons t(km) = tm. On a, en nous intéressant aux égalités, que nous réécrivons
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 (1)
où c1 et c2 sont des constantes réelles à déterminer, d’après les conditions initiales.
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
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.
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).
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:
À 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 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=2 b = –3 c=5 β = 15 γ = 11
La procédure TriFusion prend donc un temps T(n) donné par:
t(n) = 2n2 – 3n + 5 µsec si n ≤ n0
T(n/2) + T(n/2) + 15n + 11 µsec 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.
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.
Pour calculer fn, il suffit donc de calculer Fn–1 et de prendre l'élément du coin inférieur droit.
si k = 0 (matrice identité)
Fk = F × Fk–1 si k impair, k > 0
F ×F
k/2 k/2 si k pair, k > 0.
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 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).
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.
Le temps mis par cet algorithme CarréDPR pour traiter un exemplaire de taille n se calcule
comme suit:
a n + b
t(n) =
( n2) lg3 + c t ( n2 ) + d t ( n2 ) si non Petit (n)
e n 2 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.