Académique Documents
Professionnel Documents
Culture Documents
Exercice 1
1) Expliquez la différence entre les notations O() et Ω(), sans donner leur définition formelle.
O() exprime une borne supérieure sur la consommation de ressources. Ω() exprime une borne
inférieure sur la consommation de ressources.
2) Les algorithmes diviser-pour-régner et de programmation dynamique sont tous deux basés sur
une relation de récurrence. Expliquez cependant la différence fondamentale entre les deux
techniques de conception.
Un algorithme vorace est un algorithme qui fait toujours le choix qui lui semble le
meilleur sur le moment. Autrement dit, il fait le choix localement optimal, dans l’espoir
que ce choix conduira à une solution globalement optimale.
Exercice 2
1) Complexité
Le «if» s’exécute en O(1) et le «return» effectue 3 T(n-1) appels récursifs; la complexité du code
précédent sera donc sous la forme T(n) = 3*T(n-1) + 1 avec T(0) = 1. on aura donc:
T(n) = 3 * T(n-1) + 1
= 3( 3T(n-2) + 1) +1 = 32 T(n-2) + 3 + 1
= 33 T(n-3) + 3² + 3 + 1
…
= 3n T(0) + 3^(n-1) + 3^(n-2) + … + 3 + 1 or T(0) = 1
= 3n + 3^(n-1) + 3^(n-2) + … + 3 + 1
= [ 3^(n+1) – 1] / 2 ~ 3^n → T(n) = O(3n)
2) Algorithme
int T(int n ) {
return T[n];
}
Complexité: O(n)
Exercice 3
2) On a T(n) = 3 T(n/2) + n
0 n T(n) = 3 T(n/2) + n
/ | \
1 n/2 n/2 n/2 T(n/2) = 3 T(n/ 2²) + n/2
/ | \
2 n/2² … n/2² T(n/2²) = 3 T(n/2³) + n/2²
…
k 1 … 1 T(n/2^k) = 3 T(2^k+1) +
n/2^k
on a n/2^k = 1 → k = log2 n
c0 = 3⁰ n
c1 = 3(n/2) = 3/2 n
c2 = 3² (n/2²) = (3/2)² n
…
ck = 3^k (n/2^k) = (3/2)^k n
T(n) = c0 + c1 + … + ck
= n( 1 + 3/2 + (3/2)² + … + (3/2)^k)
= n ( (3/2)^k+1 – 1 ) / 3/2 – 1
= 2n ( (3/2)^log2 n – 1)
or (3/2)^log2 n = elog2 n . ln 3/2
= e ln n / ln 2 (ln 3 – ln 2)
= e ln n (log3 2 – 1 ) ~ e ln n = n
T(n) = 2 n . n → T(n) = O(n²)
6) Méthode générale
T(n) = 2T(n/2) + n lg n ,
bien qu’elle ait la forme correcte : a = 2, b = 2, f (n) = n lg n et nlogb a = n. On pourrait
penser que le cas 3 de la méthode générale s’applique, puisque f (n) = n lg n est plus grande
asymptotiquement que nlogb a = n. Le problème est qu’elle n’est pas polynomialement plus grande.
Le rapport f (n)/nlogb a = (n lg n)/n = lg n est asymptotiquement plus petit que n´ pour
toute constante positive ´. En conséquence, la récurrence tombe dans le fossé situé
entre le cas 2 et le cas 3
Exercice 4:
1) Le cas le plus défavorable intervient pour le tri rapide quand la routine de partitionnement
produit un sous-problème à n − 1 éléments et une autre avec 0 élément.
Sa complexité est O(n²)
Arbre récursif de TRI-RAPIDE dans lequel PARTITION produit toujours une décomposition 9-1,
donnant ainsi un temps d’exécution O(nlgn).
Exercice 6
Exercice 7
#include <stdio.h>
#define MAX 100
int main(void){
int i,j,n; int T[MAX][MAX];
printf("Entrez le nombre de lignes d´esir´e (<100)");
scanf("%d",&n);
for(i=0;i<n;i++){
T[i][0]=1;
T[i][i]=1; }
for(i=1;i<n;i++)
for(j=1;j<i;j++)
T[i][j]= T[i-1][j-1]+T[i-1][j];
for(i=0;i<n;i++){
for(j=0;j<i+1;j++)
printf("%3d ",T[i][j]);
printf("\n");}
return 0; }
Exercice 8
recherche dichotomique:
la complexité dans le pire des cas se fera en O( log n ).
Exercice 9
Coupons le tableau en deux moitiés : A[s..m] et A[m + 1..f]. Les trois cas ci-dessous correspondent
à trois positions de l’élément de milieu A[m] par rapport à l’intervalle [a, b]
À gauche : A[m] < a. Dans ce cas-là tous les éléments de la moitié gauche du tableau sont aussi <
a, et
ne peuvent pas appartenir à l’intervalle demandé [a, b]. On va chercher la valeur encadrée dans la
moitié droite seulement.
Dedans :a 6 A[m] 6 b. On a déjà trouvé une valeur encadrée A[m]. On retourne son indice.
À droite :b < A[m]. Ce cas est symétrique au premier, la recherche peut être limitée à la moitié
gauche
du tableau.
Cette analyse mène à la fonction récursive suivante chercher(s,f) qui renvoie l’indice de la valeur
encadrée
dans le tableau A[s..f] (ou ⊥ s’il n’y en a pas. On suppose que le tableau A, et les bornes a,b sont
des
variables globales.
fonction chercher(s,f)
// cas de base
si (s=f)
si (A[s] ∈ [a; b])
retourner s
sinon retourner ⊥
// on divise pour régner
m=(s+f)/2
si A[m] < a
ind= chercher(m+1,f)
sinon si a 6 A[m] 6 b
ind=m
sinon
ind=chercher(s,m)
retourner ind
Analysons sa complexité.
On a réduit un problème de taille n à un seul problème de la taille n/2 et des petits calculs
en O(1), donc la complexité satisfait la récurrence :
T(n) = T(n/2) + O(1).
En la résolvant par Master Theorem on obtient que T(n) = O(log n).
Exercice 10
1) Algorithme 1 Naïf
pour i de 1 à n faire
c←0
pour j de 1 à n faire
si E[j] = E[i] alors
c←c+1
si c > n/2 alors
retourner E[i] est majoritaire
retourner Pas d'élément majoritaire.
Complexité : nombre total de comparaisons = n².
2) Principe :
Couper E en deux tableaux E1 et E2 de tailles n/2 (on suppose n pair).
S'il existe un élément majoritaire x dans E, alors x est majoritaire dans au moins une
des deux listes E1 et E2 (en eet si x non majoritaire dans E1, ni dans E2, alors dans E,
cx ≤ n/4 + n/4 = n/2).
Algorithme récursif : calculer les éléments majoritaires de E1 et de E2 (s'ils existent) avec le
nombre total d'occurences de chacun et en déduire si l'un des deux est majoritaire dansE.
L'algorithme suivant Majoritaire(i, j) renvoie un couple qui vaut (x, cx) si x est majoritaire dans le
sous tableau E[i..j] avec cx occurences et qui vaut (−, 0) s'il n'y a pas de majoritaire dans E[i..j],
l'appel initial étant Majoritaire(1, n). La fonction Occurence(x, i, j) calcule le nombre d'occurences
de x dans le sous-tableau E[i..j].
Algorithme 2 Majoritaire(i, j)
si i = j alors
retourner (E[i], 1)
sinon
(x, cx) = Majoritaire(i, b(i + j)/2c)
(y, cy) = Majoritaire(b(i + j)/2c + 1, j)
si cx 6= 0 alors
cx ← cx + Occurence(x, b(i + j)/2c + 1, j)
si c
y 6= 0 alors
c
y ← cy + Occurence(x, i, b(i + j)/2c)
si cx > b(j − i + 1)/2c alors
retourner (x, cx)
sinon
si c
y > b(j − i + 1)/2c alors
retourner (y, cy)
sinon
retourner (−, 0)
Complexité : le nombre total de comparaisons dans le pire des cas C(n) vérie la relation (on
suppose que n est une puissance de 2) :
C(n) = 2(C(n/2) + n/2) avec C(1) = 0
On en déduit C(n) = n log2(n). : avec le théorème général de résolution des récurrences du Cormen :
Soient a ≥ 1 et b > 1 deux constantes, soit f(n) une fonction et soit T(n) dénie pour les entiers non
négatifs par la récurrence T(n) = aT(n/b) + f(n). T(n) peut alors être borné de la façon suivante.
1. Si f(n) = O(nlogb a−ϵ) pour une certaine constante > 0, alors T(n) = Θ(nlogb a).
2. Si f(n) = Θ(nlogb a), alors T(n) = Θ(nlogba log n).
3. Si f(n) = Ω(nlogb a+ϵ) pour une certaine constante > 0, et si af(n/b) ≤ cf(n) pour une
certaine constante c < 1 et pour tout n susamment grand, alors T(n) = Θ(f(n)).
Ici f(n) = n = Θ(n), on est dans le deuxième cas, et C(n) = Θ(nlog2 2 log n)
3) Pour améliorer l'algorithme précédent, on va se contenter dans un premier temps de mettre au
point un algorithme possédant la propriété suivante : soit l'algorithme garantit que E ne possède pas
d'élément majoritaire, soit l'algorithme fournit un entier p > n/2 et un élément x tels que x
apparaisse au plus p fois dans E et tout élément autre que x apparaît au plus n − p fois dans E.
Remarque :soit x vériant la propriété, alors aucun autre élément z 6= x ne peut être majoritaire (car
cz ≤ n−p < n/2), donc, dans ce cas, x est un candidat-majoritaire. Autrement dit un algorithme
vériant les propriétés de l'exercice nous fournit :
soit la garantie qu'il n'existe aucun élément majoritaire,
soit un candidat-majoritaire x, dont on peut vérier ensuite s'il est vraiment majoritaire en
reparcourant une fois le tableau (soit n − 1 comparaisons).
Remarque :un élément majoritaire x est bien un candidat-majoritaire avec p = cx (donc
s'il existe un majoritaire, il sera bien proposé comme candidat-majoritaire par l'algorithme).
Exercice11
2) Algorithme Glouton :
| Trier les types de pièces par valeur décroissante.
| Pour chaque valeur de pièces, maximiser le nombre de pièces choisies.
Plus formellement, soit R la somme restante, initialisée `a S. Pour chaque valeur vi,
prendre ci = R / vi pièces, et poser R = R − ci ∗ vi.
Pour prouver l’optimalité de l’algorithme glouton avec les valeurs 5; 2 et 1 :
| Au plus une pièce de 1 (sinon une de 2)
| Au plus deux pièces de 2 (sinon une de 5 et une de 1)
| Le nombre de pièces de 5 est donc bx5c
| Conclure avec ce qui précède
Exercice 12
1)
| Trier les types de pièces par valeur décroissante.
| Pour chaque valeur de pièces, maximiser le nombre de pièces choisies.
Plus formellement, soit R la somme restante, initialisée `a S. Pour chaque valeur vi,
prendre ci = E [R / vi ] pièces, et poser R = R − ci ∗ vi.
Prouvons l’optimalité
l’algorithme retournera:
- au plus une pièce de 5 (sinon une pièce de 10)
- au plus deux pièces de 2 ( sinon une de 5 et une de 1)
- au plus une pièce de 1 (sinon une de 2)
- au plus trois pièces différentes de 10 pour R < 9
2)
- trier les pièces par ordre décroissant de valeur;
- pour chaque valeur de pièce choisie, maximiser son nombre.
4- Avec E’ = {4, 2} et R = 5, l’algorithme renvoie une pièce de 4 mais le problème n’est pas résolu.
Exercice 13
1- Algorithme glouton
- ranger les objets par ordre décroissant d’efficacité (Ei = Vi / Wi)
- pour le premier objet choisi, prendre autant de masse que possible jusqu’à remplissage du sac ou
épuisement de stock;
- faire de même avec le deuxième et ainsi de suite.
Exercice 14
Exercice 15
2-
Algorithme récursif :
P(i, j) :
Si i = 0 et j > 0 :
P := 1
Sinon
Si i > 0 et j = 0 :
P := 0
Sinon
Si i > 0 et j > 0 :
P := q1*P(i - 1,j) + q2*P(i, j - 1)
Fsi
Fsi
Fsi
3-
Pour S = 1, i+j
P[0, S] := 1
P[S, 0] := 0
Pour k=1, S1
P[k, Sk] := q1P[k1, Sk] + q2P[k, Sk1]
Finpour
Finpour
Le temps d’exécution est en O(n²) pour le calcul de P(n,n).
Exercice 16
1. complexité spatiale : n * n
2. complexité temporelle : n* n sommes
somme := tab[1].val
pour cpt := 2 à mfaire somme := somme + tab[cpt].val
3. complexité spatiale : 3 * m
4. complexité temporelle : m-1
Exercice 17
1- C’est une instance de sac-à-dos fractionnaire (avec le pouvoir calorifique qui remplace le coût
dans
le problème). L’algo glouton de cours est comme ceci :
–Classer les produits dans l’ordre décroissant de coûts par kilo (ici pouvoir calorifique).
–Prendre autant de premier produit que possible (jusqu’au remplissage de sac ou épuisement de
stock).
–Pareil pour le deuxième produit etc. . .
Cela donne les produits classés comme ceci : essence, charbon, ethanol, bois.
Et le contenu de sac : essence - tous les 10 kg ; charbon - tous les 12 kg ; ethanol - 13 kg. Le sac est
plein
2-
a)
L’observation principale est la suivante : si un sommet est noir, alors tous ses voisins doivent être
blancs ; et vice versa. Ainsi on fixe la couleur d’un sommet (par exemple noir) ; on colorie tous ses
voisins en blanc ; tous leurs voisins en noir etc (en fait c’est un parcours en largeur). Soit on arrive à
colorier ainsi tout le graphe, soit on découvre une anomalie, et dans ce cas-là le 2-coloriage est
impossible.
Voici le pseudo-code (en supposant que le graphe est représenté par les listes d’adjacence, est
Adj(v) est la liste des voisins du sommet v). Tous les sommets sont gris au départ, et on les colorie
en parcourant le graphe.
c)
Si l’algorithme dit "coloriage trouvé", alors tous les sommets sont coloriés (il ne reste plus de
sommets gris), parce que le BFS (parcours en profondeur) dans un graphe connexe non-orienté
visite tous les sommets. Les voisins de chaque sommet blanc sont noirs et vice versa grâce à la
boucle principale (s’il y avait deux voisins de même couleur, ça serait détecté au moment ou le
deuxième voisin sort de la file). On a donc démontré que si l’algo dit "coloriage trouvé", alors c’est
vraiment le cas.
Pour la réciproque, il reste à prouver, que si le coloriage est possible l’algorithme le trouvera.
Effectivement, si le coloriage est possible, alors il existe un coloriage où le sommet s est noir (sinon
on inverse la couleur de tous les sommets). Dans ce coloriage tous les voisins de s doivent être
blanc, tous leurs voisins noirs etc (c-à-d tous les sommets à une distance paire de s sont noirs, tandis
que les sommets à une distance impaire sont blanc). Mais c’est exactement le coloriage calculé par
l’algorithme !
d)
Malheureusement cette méthode ne marche pas pour 3 couleurs (ou plus) puisque la couleur d’un
sommet
ne détermine pas les couleurs de ses voisins comme c’était le cas pour 2 couleurs.
Exercice 18
2-
On peut maintenant régler la hauteur des étagères. Nous allons donc chercher `a minimiser
l’encombrement, défini comme la somme des hauteurs du plus grand livre de chaque étagère
utilisée. On voit dans l’exemple suivant que l’algorithme glouton précédent ne trouve pas la
solution optimale.
On pose L = 3, n = 3, w1 = 2, w2 = w3 = 1, h1 = 1, h2 = h3 = 7. L’algorithme glouton place b1 et b2
sur la première étagère, de hauteur 7, et b3 sur une deuxième étagère, de hauteur 7 aussi, fournissant
un encombrement total de 14. La solution optimale fournit un encombrement total de 8 en plaçant
b1 seul sur la première étagère et b2 et b3 sur la deuxième étagère.
Fait par EM