0% ont trouvé ce document utile (0 vote)
38 vues12 pages

Complex It É

Le document traite de la complexité algorithmique, en présentant des exercices sur la détection de la présence du caractère 'a' dans une chaîne de caractères à l'aide de différentes solutions en Python. Il définit la complexité d'un algorithme en termes de ressources nécessaires, distingue la complexité temporelle et spatiale, et introduit la notation O pour évaluer la complexité asymptotique. Plusieurs exemples illustrent le calcul de la complexité pour différents algorithmes, notamment le tri par sélection et la recherche séquentielle.

Transféré par

Said Oumansour
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats DOCX, PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
38 vues12 pages

Complex It É

Le document traite de la complexité algorithmique, en présentant des exercices sur la détection de la présence du caractère 'a' dans une chaîne de caractères à l'aide de différentes solutions en Python. Il définit la complexité d'un algorithme en termes de ressources nécessaires, distingue la complexité temporelle et spatiale, et introduit la notation O pour évaluer la complexité asymptotique. Plusieurs exemples illustrent le calcul de la complexité pour différents algorithmes, notamment le tri par sélection et la recherche séquentielle.

Transféré par

Said Oumansour
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats DOCX, PDF, TXT ou lisez en ligne sur Scribd

CPGE-AGADIR MP-PSI-TSI

COMPLEXITE ALGORITHMIQUE

1. INTRODUCTION
Exercice
Ecrire en python une fonction qui prend en argument une chaîne de caractères et détermine si le caractère 'a' est
présent dans la chaîne (on retourne soit True soit False).

 Analysons plusieurs solutions :

Première solution Deuxième solution

def contienta1(chaine): def contienta2(chaine):


k=0 for i in range(len(chaine)):
N=len(chaine) if chaine[i]=='a':
trouve=False return True
while(trouve == False and k < N): return False
if chaine[k]=='a':
trouve = True
k=k+1
return trouve

Troisième solution Quatrième solution

def contienta3(chaine): def contienta4 (chaine):


n=chaine.count('a') return('a' in chaine)
return bool(n)

 Quelques questions:

1. que remarquez-vous concernant cet exercice?


2. Le Coûte le plus court ! Est-il meilleur?
3. Comment peut-on désigner le meilleur Coûte parmi ces quatre solutions?

2. DÉFINITION DE LA COMPLEXITÉ D'UN ALGORITHME


 La complexité d'un problème mathématique P est une mesure de la quantité de ressources nécessaires à la
résolution du problème P.
 Cette mesure est basée sur une estimation du nombre d'opérations de base effectuées par l'algorithme en
fonction de la taille des données en entrée de l'algorithme.
 Généralement, pour le même problème P, on peut trouver plusieurs algorithmes (Alg1; Alg2;...;Algn).
 L'objectif de la complexité est d'évaluer le coût d'exécution de chaque algorithme afin de choisir le meilleur.

Problème:
Comment évaluer le coût d'exécution d'un algorithme donné?

Complexité 1 /12 M.GUEROIHI


3. TYPES DE COMPLEXITÉ
En fonction des ressources utilisées pour évaluer la complexité d'un algorithme, on sera amené à distinguer deux
types de complexité: complexité temporelle et complexité spatiale.
Complexité temporelle (en temps)
La complexité temporelle d'un algorithme est le nombre d'opérations élémentaires (affectations, comparaisons,
opérations arithmétiques) effectuées par un algorithme.
Complexité spatiale (en espace)
La complexité en mémoire donne le nombre d'emplacements mémoires occupés lors de l'exécution d'un
programme.
Remarque : Dans ce cours, nous nous intéressons uniquement à la complexité temporelle.

4. LA NOTATION O :(Complexité asymptotique)


Définition
Soit T(n) une fonction qui désigne le temps de calcul d'un algorithme A.
On dit que T(n) est en grand O de f(n): T(n)= O(f (n)) si et seulement si:
n0∈ N *,  c ∈ℝ, n >= n0 :T(n) <= c *f (n).

La notation O(f (n)) est aussi appelée Notation de Landau : (Complexité asymptotique) (i.e.quand n →∞ )
Exemples

(on écrit aussi 3n +6∈O(n))


Exemple1:
Prouvons que la fonction T(n)=3n +6 est en O(n)
But: trouver une constante c ∈ℝet un seuil n0∈ N *, à partir du quel T(n) <c.n
On remarque3n+6<9n si n>2
3*2+6 <9*2
3*3+6 <9*3
3*4+6 <9*4 On déduit donc que c=9 fonctionne à partir d’un seuil n0=2
3*5+6 <9*5
.
.
.
Remarque:
On ne demande pas d'optimisation (le plus petit c ou n0qui fonctionne), juste de donner des valeurs qui fonctionnent;
c =10 et n0 =5 est donc aussi acceptable;
3*5+6 <10*2
3*6+6 <10*3
3*7+6 <10*4
Exemple2:

Complexité 2 /12 M.GUEROIHI


2
Prouvons que la fonction : T(n)= n +3n est en O(n2)
But: trouver une constante c ∈ℝet un seuil n0∈ N *, à partir duquel T(n) <c.n
Cherchons d'abord la constante c ; c =1 ne peut pas marcher, essayons donc c =2;
On doit alors trouver un seuil n0∈ N *, à partir du quel :n2 +3n <=2n2
On remarque n2 +3n <=2n2 si n>3
On déduit donc que c=2 fonctionne à partir d’un seuil n0=3

5. CLASSES DE COMPLEXITE LES PLUS USUELLES


On voit souvent apparaître les complexités suivantes:
Complexité Nom courant Description

O(1) Constante Le temps d'exécution ne dépend pas des données traitées, ce qui est assez rare!

O(log(n)) Logarithmique augmentation très faible du temps d'exécution quand le paramètre croit.

augmentation linéaire du temps d'exécution quand le paramètre croit(si le paramètre


O(n) Linéaire
double, le temps double).

O(nlog(n)) Quasi-linéaire augmentation un peu supérieure à O(n)

quand le paramètre double, le temps d'exécution est multiplié par4. Exemple:


O(n2) Quadratique
algorithmes avec deux boucles imbriquées.
ici, nk est le terme de plus haut degré d'un polynôme en n ; il n'est pas rare de voir des
O(nk ) Polynômiale
complexités en O(n3) ou O(n4).

O(kn) Exponentielle quand le paramètre double, letemps d'exécution est élevé à la puissance k avec k > 1.

O(n!) Factorielle asymptotiquement équivalente à nn

6. COMMENT MESURER LA COMPLEXITE D'UN ALGORITHME


a. Le coût des instructions élémentaires
 Opération élémentaire.
On appelle opération de base, ou opération élémentaire, toute:
 Affectation;
 Test de comparaison: ==;<;<=;>=;!=
 Opération de lecture(input)et d’écriture (print);
 Opération arithmétique:+;- ; *;/ ; %
Lecoûtd'uneopération élémentaireest égal à 1.
Exemple1: Que vaut le coût de l'algorithme A
somme = n +1 #instr1
somme = somme * n #instr2
somme = somme/2 #instr3
Coût(A) =Coût(inst1)+Coût(instr2)+Coût(instr3)
= 2 +2+2
=6

Complexité 3 /12 M.GUEROIHI


b. Le coût des instructions composées
On appelle opération composée, toute instruction contenant:
 L'exécution d'une instruction conditionnelle :
Si (test) alors
Q1
Sinon
Q2
Finsi
Le nombre d'opérations est: Coût(P) = Coût (test)+ max (Coût(Q1),Coût(Q2))
 L'exécution d'une boucle : est égal à la multiplication de nombre de répétitions par la somme du coût
de chaque instruction xi du corps de la boucle;
Coût (bouclefor)= ∑ Coût (xi)
Coût(boucle while)= ∑ (Co ût (comparaison )+Coû t (xi) ¿ )¿
 L'appel d'une fonction : Lorsqu'une fonction ou une procédure est appelée, le coût de cette fonction
ou procédure est le nombre total d'opérations élémentaires engendrées par l'appel de cette fonction.
Exemple2: Que vaut le coût de l'algorithme B
if i%2==0:
n=i//2
else:
i=i+1
n=i//2
Coût (B)=Coût(i%2==0)+max(Coût(n = i//2),Coût(i = i +1 , n = i//2))
= 2 + max(2,4) = 6

Exemple3: Que vaut le coût de l'algorithme C


i=1
while i <= n :
somme=somme+i
i=i+1

Coût(C)=1+ ∑ (Coû t (i<¿ n)+ Coû t (somme =somme +i)+Co û t (i=i+ 1))
=1+n+2n+2n =1+5n

c. La notation O : motivation
 Les calculs à effectuer pour évaluer le temps d'exécution d'un algorithme peuvent parfois être longs et
pénibles;
 De plus, le degré de précision qu'ils requièrent est souvent inutile;
 On aura donc recours à une approximation de ce temps de calcul, représenté par la notation O(.);

d. Règles de calcul : simplifications


 On calcule le temps d'exécution comme avant, mais on effectue les simplifications suivantes:
o On oublie les constantes multiplicatives (elles valent 1);
o On annule les constantes additives;
o On ne retient que les termes dominants;
 Exemple (simplifications)

Soit un algorithme effectuant T(n) = 4n3 - 5n2 +2n +3 opérations;

o On remplace les constantes multiplicatives par 1 : 1n3 - 1n2 + 1n +3


o On annule les constantes additives : n3 - n2 + n +0
o On garde le terme de plus haut degré : n3 + 0

Complexité 4 /12 M.GUEROIHI


3
Et on a donc : T(n)= O(n ).
7. EXEMPLES DE CALCUL DE COMPLEXITÉ
Exemple 1 Exemple 2

 La fonction suivante permet de La fonction suivante permet de retourner la somme des éléments d’une
retourner le quotient et le reste de liste:
la division d’un nombre entier a def Somme(L):
par b.
s=0
def division (a ,b):
for i in rang(len(L)) :
q=a//b
s=s+L[i]
r=a%b
return s
return(q,r)
Exemple
 Exemple >>> L =[1, 2, 8, 4]
>>>x,y=10,3 >>>Somme(L)
>>>division(x , y) 15
3 , 1
 Le paramètre de complexité est la taille de la liste d'entrée L.
 Le nombre d'opérations est:5  en fixant i on exécute 2 opérations: (addition et affectation)
 Temps de calcul est constant  Nombre de fois d'exécution de ces 2 opérations est: len(T)
 Complexité: O(1)  Le nombre total d'opérations est : 4 * len(L) + 3
 Complexité: O(len(L))= O(n)

Exemple 3 : remplir un tableau Exemple 4 : remplir une matrice

def RemplirTab (T): def RemplirMat(M):


n=len(M)
for i in range(len(T)):
p=len(M[0])
print("T[",i, "]=",end=' ')
for i in range(n):
T[i]=int(input()) for j in range(p):
 Le paramètre de complexité est la taille du print("T[",i,"][",j,"]=")
tableau d'entrée T. T[i][j]=int(input())
 en fixant i on exécute 4 opérations: (print,  Coût pour saisir une valeur est : 4
input,int et affectation)  Le nombre d'itérations de la boucle sur j pour i
 Nombre de fois d'exécution de ces 4 opérations fixé égal à : p
est: len(T)  Le nombre total pour lire toutes les valeurs pour
 Le nombre total d'opérations est : 4 * len(T) i fixé égal à 4p
 Complexité: O(len(T))= O(n)  Le nombre total d'opérations est : 2 +4p.n
 Complexité : O(n.p)

Complexité 5 /12 M.GUEROIHI


Exemple 5 : Produit matriciel

def prodMatrice(A,B):
n=len(A) #nombre de lignes de A
m=len(A[0]) #nombre de colonne de A
p=len(B[0]) #nombre de colonnes de B
C=[p*[0] for i in range(n)]
for i in range(0,n):
for j in range (0,p):
s=0;
for k in range (0,m):
s = s + A[i][k]*B[k][j]
C[i][j]=s
return C

 On suppose que A et B sont deux matrices carrées d'ordre n = m = p


 Coût pour calculer une valeur de s est : 3(produit, addition et affectation)
 Le nombre d'itérations de la boucle sur k pour j fixé égal à m=n
 Le nombre d'itérations de la boucle sur j pour i fixé égal à p=n
 Le nombre total d'opérations est : T(n)=4+ n + n(n(2+n(3))
 Complexité: O(n3)

Exemple6 : Tri par sélection


def TriSelection(T):
n=len(T)
for i in range(n-1):
Posmin=i
for j in range(i+1,n):
if T[j]<T[Posmin]:
Posmin=j
#Permutation
T[i],T[Posmin]=T[Posmin],T[i]

 Coût des échanges:


o Le tri par sélection sur n nombres fait n-1 échanges, ce qui fait : 3(n- 1) affectations
 Coût des recherches de minimum:
o On recherche le minimum parmi n éléments : au plus 3(n -1) opérations. (c'est le nombre
d'itérations de la boucle sur j pour i fixé égal à n- 1)
o On recherche le minimum parmi n-1 éléments : auplus3 (n-2) opérations. (c'est le nombre
d'itérations de la boucle sur j pour i fixé égal à n-2)
o On recherche en suite le minimum parmi n-2 éléments : 3(n-3) tests.
o ...
 Le nombre total de tests est : 3(1+2+3+ … +(n- 2)+(n -1))=3( (n- 1)n)/2
 Le nombre total d'opérations est : 3(n- 1) + 3((n- 1)n)/2
 Donc, la complexité est quadratique : O(n2)

Complexité 6 /12 M.GUEROIHI


Exemple 7 : recherches séquentielle
def Recherche_Seq(T,x):
i=0
n=len(T)
for i in range(n):
if T[i]==x :
return True
return False

 Le nombre d'opérations avant for est : 3


 La boucle for contient 2 opérations : (test et return True)
 Le nombre de fois d'exécution de ces 2 instructions dans le pire de cas est n
 Le nombre d'opérations après la boucle for est : 1(return False)
 Le nombre d'opérations total est : 3+2n+1
 Complexité : O(n)

Exemple 8 : Recherche dichotomique


def RechDichotomique(T,x):
g,d=0,len(T)-1
while g <= d:
m=(g+d)//2
ifT[m]==x: returnTrue
ifT[m]<x:
g=m+1
else:
d=m-1
return False

 Soit k le nombre de passages dans la boucle while.


 on divise le nombre d'éléments restants par 2 jusqu'à ce qu'il n'en reste qu'un (k divisions)
((((n/2)/2)/2)/…./2)=1
k
 Donc n/2 =1 et ainsi k=log2n
 Complexité : O(log2(n))

Complexité 7 /12 M.GUEROIHI


Exemple.9 : les tours de Hanoï

def hanoi (n , A='A' , B='B', C='C'):


if n > 0:
hanoi(n-1, A, C, B)
print("Déplacer le disque %d de la tige %s vers la tige %s."% (n, A, C))
hanoi(n-1, B, A, C)

 L'évaluation de la complexité de cet algorithme est assez simple. Nous allons chercher à savoir combien de
déplacements de disques sont nécessaires pour arriver à nos fins. Très simplement, la fonction calculant ceci
peut être définie de la manière suivante (on peut se baser sur la fonction ci-dessus) :
 T(0) = 0; T(1) = 1; T(n) = 2*T(n-1)+1. On peut démontrer par récurrence que ceci est égal à T(n) = 2n-1 :
 On a T(n+1) = 2*T(n)+1. En supposant que T(n) = 2 n-1, on a T(n+1) = 2*(2n-1)+1. On développe ensuite en
T(n+1) = 2*2n -2+1 ce qui nous donne au final T(n+1) = 2 n+1-1. On a ainsi démontré que si c'est vrai pour n,
alors c'est vrai pour (n+1). Comme on a T(1) = 2*0+1 = 2 1-1 = 1, c'est vrai pour tous les n supérieurs à 1. La
complexité exacte de l'algorithme présenté ci-dessus est donc en 2n-1 pour n disques à déplacer de la tour
 On trouve T(n)=2n - 1
 Donc lacomplexité est éxponentielle O(2n)

8. DIFFÉRENTESNUANCESDE COMPLEXITÉ
On distingue 3 types de complexités: Complexité au pire des cas, dans le meilleur des cas et en moyenne
des cas.
8-1 : Complexité au pire des cas
La complexité au pire est le plus grand nombre d'opérations qu'aura à exécuter l'algorithme sur un jeu de
données de taille fixée à n.
Exemple: Recherche d'un élément dans un tableau
def find(T,x): On note n la longueur du tableau T(n=len(T)).
for e in T:
Dans le pire des cas : quand l'élément recherché x est le dernier (dans la case
if e==x:
n-1) ou est absent.
return True
return False Donc la complexité dans le pire est Cmax (n)= n

8-2 : Complexité dans le meilleur des cas


La complexité au meilleur est le plus petit nombre d'opérations qu'aura à exécuter l'algorithme sur un jeu de
données de taille fixée. C'est une borne inférieure de la complexité de l'algorithme sur un jeu de données de
taille n.
Exemple: Recherche d'un élément dans un tableau
On considère le même exemple précédent.
Dans le meilleur des cas : quand l'élément recherché x se trouve en 1ere position.
Donc la complexité dans le meilleur des cas est : Cmin(n)=1

Complexité 8 /12 M.GUEROIHI


8-3 : Complexité en moyenne des cas
La complexité en moyenne est la moyenne des complexités de l'algorithme sur des jeux de données de taille n.
Cette complexité en moyenne reflète le comportement "général" de l'algorithme si les cas extrêmes sont rares ou
si la complexité varie peu en fonction des données.

Tmoy (n)={∑ Pr ( d ) .C ( d ) ,dϵ Dn}


Où Pr(d) est la probabilité d'avoir la donnée d en entrée de l'algorithme.
Exemple : Recherche d'un élément dans un tableau
En moyenne, dans l'hypothèse où la probabilité de trouver x dans le tableau est q et si x est présent, il peut se
trouver dans n'importe quelle case avec la même probabilité, à savoir 1/n
Alors la probabilité que x se trouve dans la ième case est :q * 1/n, d'où:
Cmoy (n)= q *(1/n + 2/n + 3/n + …+ n/n) + (1-q)*n=q(n+1)/2 + n(1-q)
Si q=1, la complexité en moyenne des cas sera Cmoy (n)= (n+1)/2

9. COMPLEXITÉ ET RÉCURSIVITÉ
Il existe diverses techniques pour la résolution des équations de récurrence.
 méthode des fonctions génératrices et décomposition des fractions rationnelles
 Transformée en Z…

Résolution des récurrences.

 C(n) = C(n-1) + b
 solution : C(n) = c(0) + b*n = O(n)
 exemples : factorielle, recherche séquentielle récursive dans un tableau

 C(n) = a*C(n-1) + b, a ≠ 1
 solution : C(n) = an*(C(0) – b/(1-a)) + b/(1-a) = O(an)
 exemples : répétition a fois d'un traitement sur le résultat de l'appel récursif

 C(n) = C(n-1) + a*n + b


 solution : C(n) = c(0) + a*n*(n+1)/2 + n*b = O(n2).
 exemples : traitement en coût linéaire avant l'appel récursif, tri à bulle

 C(n) = C(n/2) + b
 solution : C(n) = C(1) + b*log2(n) = O(log(n))
 exemples : élimination de la moitié des éléments en temps constant avant l'appel récursif, recherche
dichotomique récursive

 C(n) = a*C(n/2) + b, a ≠ 1
 solution : C(n) = nlog2(a) *(c(1) – b/(1-a)) + b/(1-a) = O(nlog2(a))
 exemples : répétition a fois d'un traitement sur le résultat de l'appel récursif dichotomique

 C(n) = C(n/2) + n
 solution : C(n) = O(n)
 exemples : traitement linéaire avant l'appel récursif dichotomique

 C(n) = 2*C(n/2) + a*n + b


 solution : C(n) = O(n*log(n))
 exemples : traitement linéaire avant double appel récursif dichotomique, tri fusion

Complexité 9 /12 M.GUEROIHI


TD : Complexité

Exercice 1
On considère le programme suivant:
def Algo( n):
for i in range(0,n):
Algo1(n)
Algo2(n)
Algo3(n)
 Sachant que Algo1(n) s'effectue en temps O(log(n)),Algo2(n) en temps O(n)etAlgo3(n) en temps O(n2), Quelle est
la complexité de Algo(n)?

Exercice 2 :
Quelle est la complexité du programme suivant :
def Algo(n):
res = 1;
for i in range(0,n):
res = res + i
for i in range(0,n):
for j in range(0,i):
res = res * (i+j)
return res

Exercice 3 :
Quelle est la complexité du programme suivant:
def f(x, n):
if n < 1:
return n
S = 0
for i in range(0,n):
S += x/(i+n)

return S + f(x,n/2)

Exercice 4
1- Que vaut la complexité de l'algorithme suivant:
i=1
while i <= n :
i=i*2
2- Le code ci-dessous consiste à programmer la fonction remove. Analyser sa complexité?
def SupprimerElement(L,a):
i=0
if a in L:
while L[i]!=a:
i=i+1
L[i:i+1]=[]

Complexité 10 /12 M.GUEROIHI


Exercice 5
Soient les 3 fonctions suivantes permettant de calculer la valeur d'un polynôme : p(x) = a0+a1x+a2x2+...+anxn
en un point x (c'est-à-dire pour une valeur x donnée).
Les coefficients du polynôme sont stockés dans une liste : A=[a0, a1, a2..., an-1 , an]
def f1(A,x) :#méthode naïve
n =len(A)
p=A[0]
for i in range(1,n) :
p = p + A[i]* x**i
return p
x**i : n’est pas une opération élémentaire
def f2(A,x) :# elle utilise le fait que xi = xi-1* x
n =len(A)
p=A[0] ;
q = 1;
for i in range(1,n) :
q = q * x ;
p = p +A[i]* q ;
return p

#algorithme de Horner ;
il calcule, DANS CET ORDRE, les valeurs de :an, anx+an-1, puis (anx+an-1) x + an-2, etc.
def f3(A,x) :# utilisant la méthode de Horner
n =len(A)
p = A[n-1] ;
for i in range(n-1,0,-1) :
p = p*x + A[i-1]
return p
Comparer leur complexité au pire cas.

Exercice 6
Écrire une fonction qui prend un tableau d’entiers T en argument et renvoie le tableau des sommes cumulées
croissantes correspondantes, autrement dit un tableau S de même taille dont la k-ième composante vaut :
k
S [ k ] =∑ t [i]
i=0

Evaluer la complexité de cette fonction.


Est-il possible d’en écrire une version plus efficace ? Donner alors sa complexité

Exercice 7
Soit u la suite définie par u0 = 1 et pour n ∈ N, un+1 = sin(un).
1. Écrire une fonction nommée suite prenant n ∈ N en argument et renvoyant un.
2. Que calcule la fonction suivante : de fmystere(n):
s = 0
for k in range(n+1):
s = s + suite(k)
return s

3. Déterminer en fonction de n le nombre d’additions et de calculs de sinus nécessaires pour calculer


mystere(n).

Complexité 11 /12 M.GUEROIHI


4. Écrire une autre fonction qui renvoie les mêmes valeurs que mystere mais avec une meilleure complexité.

Complexité 12 /12 M.GUEROIHI

Vous aimerez peut-être aussi