Complexité d'algorithmes

Fermé
Lucie22 - 18 mars 2022 à 21:17
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 - 19 mars 2022 à 14:57
Bonsoir !

J'ai du mal à comprendre la notion de complexité d'algorithmes. Par exemple, ici, je dois trouver la complexité des 4 algo' ci-dessous. Le premier n'étant pas récursif, je pense avoir trouvé qu'il s'agit d'une complexité O(n). Par contre, pour les 3 autres, je ne sais pas par où commencer...
En cours, j'ai vu la méthode des arbres récursifs à partir d'une expression T(n) donnée. Or, ici, je n'arrive pas à trouver l'expression de T(n) à partir des algo...
J'ai donc essayer de trouver leur complexité un peu "à l'oeil" en essayant de comprendre comment fonctionnait chaque algorithme et j'en suis arrivée à trouver une complexité en O(n) pour le troisième, et en O(log(n)) pour les 2 autres.


Quelqu'un pourrait-il me valider ces résultats ?
Et, le cas échéant, m'expliquer comment je suis censé procéder pour trouver la complexité d'algo récursifs ?

public class Math{

    public static int multiIter(int x, int y){ 
        int sum = 0;
        for (int i=0; i<y; i++) {
            sum += x;
        }
        return sum;  
    } 

    public static int multiRec(int x, int y){ 
        if  (x == 0){
            return 0;
        }
        else if (x%2 == 0){
            return 2*multiRec(x/2, y);
        }
        else{
            return 2*multiRec((x-1)/2, y)+y;
        }
    } 

    public static int puissanceRec(int x, int n){ 
        if (n==0){
            return 1;
        }
        else{
            return puissanceRec(x,n-1)*x;
        }
    } 

    public static int exponentiationRapide(int x, int n){ 
        if (n==0){
            return 1;
        }
        else if (n%2 == 0){
            return exponentiationRapide(x*x, n/2);
        }
        else{
            return exponentiationRapide(x*x, (n-1)/2)*x;
        } 
    }     
}




Configuration: Windows / Opera 83.0.4254.70

1 réponse

KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
19 mars 2022 à 14:57
Bonjour,

"J'ai du mal à comprendre la notion de complexité d'algorithmes."
Pour faire simple, il s'agit d'estimer le nombre de ressources que ton programme devra traiter. Dans ton cas il s'agit de la complexité en temps de calcul, mais cela pourrait aussi être une complexité en mémoire.
Cela permet d'anticiper théoriquement le comportement du programme quand on augmente le nombre de données à traiter. On peut ainsi comparer deux algorithmes entre eux et choisir lequel sera le plus adapté, par exemple le plus rapide, le moins gourmand en mémoire, ou un compromis entre les deux.

"Le premier n'étant pas récursif, je pense avoir trouvé qu'il s'agit d'une complexité O(n) [...] j'en suis arrivée à trouver une complexité en O(n) pour le troisième, et en O(log(n)) pour les 2 autres."
Je suis d'accord avec les résultats. Toutefois, au niveau du raisonnement dire qu'il est en O(n) car il n'est pas récursif est faux, on pourrait très bien réécrire les autres algorithmes en enlevant leur récursivité, ils conserveraient quand même leur complexité logarithmique en temps.
Remarque : enlever la récursivité de l'algorithme diminuerait cependant la complexité en mémoire.

"comment je suis censé procéder pour trouver la complexité d'algo récursifs ?"
On peut le faire mathématiquement, en se servant d'outils simples tels que les suites, le raisonnement par récurrence, ou plus avancés comme la comparaison asymptotique, d'où viennent notamment les notation de Landeau comme O(n)

Exemple, avec multiRec
Si x = 0 : f(x) = 1 => on est passé une fois dans la méthode
Si x > 0 et x%2 == 0 : f(x)= 1 + f(x/2) => on passe une fois dans la méthode, plus le nombre de fois pour f(x/2)
Si x > 0 et x%2 != 0 : f(x)= 1 + f((x-1)/2) = 1 + f(x/2) => on a donc un seul cas pour x > 0

Soit x=2^n : f(x)=1+f(x/2) <=> f(2^n)=1+f(2^(n-1))=2+f(2^(n-2))=3+f(2^(n-3))= ... = n + f(2^0)
Donc f(2^n) = O(n) <=> f(x) = O(ln(x))

Pour résumer :
  • multiIter : O(n) en temps, O(1) en mémoire
  • multiRec : O(ln(n)) en temps, O(ln(n)) en mémoire
  • puissanceRec : O(n) en temps, O(n) en mémoire
  • exponentiationRapide : O(ln(n)) en temps, O(ln(n)) en mémoire
0