Section courante

A propos

Section administrative du site

Permutations et factorielles

Les permutations et les factorielles sont des notions fondamentales de la combinatoire, une branche des mathématiques consacrée au dénombrement des différentes façons d'organiser, de sélectionner ou de répartir des éléments. Elles permettent de déterminer combien d'ordres distincts peuvent être obtenus à partir d'un ensemble de valeurs, de personnes, de caractères ou d'objets. Ces concepts interviennent fréquemment en informatique lorsqu'un programme doit examiner plusieurs arrangements possibles, générer des séquences, résoudre un problème d'optimisation ou évaluer le nombre de solutions envisageables.

La factorielle représente le produit de tous les entiers positifs inférieurs ou égaux à une valeur donnée. Elle est directement liée aux permutations, puisque le nombre de façons différentes d'ordonner n éléments distincts est égal à n!. La croissance extrêmement rapide de cette fonction explique pourquoi certains algorithmes combinatoires deviennent impossibles à exécuter dès que la taille des données augmente légèrement. La compréhension des permutations et des factorielles est donc essentielle pour étudier la combinatoire, les probabilités, les coefficients binomiaux, la récursivité et l'analyse de la complexité des algorithmes.

La factorielle

La factorielle d'un entier naturel n est le produit de tous les entiers positifs compris entre 1 et n.

Elle est représentée par un point d'exclamation placé après le nombre :

n!

Sa définition est :

n! = 1 × 2 × 3 × ... × n

Par exemple :

1! = 1

2! = 1 × 2 = 2

3! = 1 × 2 × 3 = 6

4! = 1 × 2 × 3 × 4 = 24

5! = 1 × 2 × 3 × 4 × 5 = 120

La factorielle peut également être représentée à l'aide de la notation de produit :

n! = πi=1n i

La factorielle de zéro

Par convention, la factorielle de zéro vaut :

0! = 1

Cette définition peut sembler inhabituelle, puisqu'aucun entier positif n'est multiplié. Elle repose cependant sur la notion de produit vide, dont la valeur est définie comme étant 1.

Cette convention permet également de conserver la relation récursive :

n! = n × (n - 1)!

Pour n = 1, on obtient :

1! = 1 × 0!

Puisque :

1! = 1

il est nécessaire que :

0! = 1

La définition de 0! simplifie également de nombreuses formules combinatoires.

Définition récursive

La factorielle peut être définie de manière récursive :

0! = 1

n! = n × (n - 1)! pour n > 0

Par exemple :

5! = 5 × 4!

4! = 4 × 3!

3! = 3 × 2!

2! = 2 × 1!

1! = 1 × 0!

En remplaçant progressivement les expressions, on obtient :

5! = 5 × 4 × 3 × 2 × 1 = 120

Cette définition illustre parfaitement le fonctionnement d'un algorithme récursif.

Algorithme récursif de la factorielle

L'algorithme suivant calcule une factorielle par récursivité :

MODULE Factorielle(n)

   SI n = 0 ALORS
      RETOURNER 1
   FIN SI

   RETOURNER n × Factorielle(n - 1)

Le cas n = 0 constitue le cas d'arrêt. Sans celui-ci, la fonction continuerait à s'appeler indéfiniment.

Cette méthode est simple et correspond directement à la définition mathématique. Elle utilise toutefois un appel de fonction supplémentaire pour chaque valeur comprise entre n et 0.

Algorithme itératif de la factorielle

La factorielle peut également être calculée avec une boucle :

MODULE Factorielle(n)

   résultat ← 1

   BOUCLE POUR i ← 2 JUSQU'A n
      résultat ← résultat × i
   FIN BOUCLE POUR

   RETOURNER résultat

La variable résultat doit être initialisée à 1, puisque cette valeur est l'élément neutre de la multiplication.

Cette version est généralement plus économique en mémoire que la version récursive, car elle ne nécessite pas l'empilement de plusieurs appels de fonction.

Exemple en Java

L'exemple suivant présente une version itérative et une version récursive du calcul de la factorielle :

  1. public class FactorielleSample {
  2.  
  3.     public static long factorielleIterative(int n) {
  4.         if (n < 0) {
  5.             throw new IllegalArgumentException(
  6.                 "La factorielle n'est pas définie pour un entier négatif."
  7.             );
  8.         }
  9.  
  10.         long resultat = 1;
  11.  
  12.         for (int i = 2; i <= n; i++) {
  13.             resultat *= i;
  14.         }
  15.  
  16.         return resultat;
  17.     }
  18.  
  19.     public static long factorielleRecursive(int n) {
  20.         if (n < 0) {
  21.             throw new IllegalArgumentException(
  22.                 "La factorielle n'est pas définie pour un entier négatif."
  23.             );
  24.         }
  25.  
  26.         if (n == 0) {
  27.             return 1;
  28.         }
  29.  
  30.         return n * factorielleRecursive(n - 1);
  31.     }
  32.  
  33.     public static void main(String[] args) {
  34.         System.out.println("5! = "
  35.             + factorielleIterative(5));
  36.  
  37.         System.out.println("10! = "
  38.             + factorielleRecursive(10));
  39.     }
  40. }

Le programme retourne :

5! = 120
10! = 3628800

Croissance de la factorielle

La fonction factorielle croît extrêmement rapidement.

n n!
0 1
1 1
2 2
3 6
4 24
5 120
6 720
7 5 040
8 40 320
9 362 880
10 3 628 800
15 1 307 674 368 000
20 2 432 902 008 176 640 000

Cette croissance est plus rapide qu'une fonction exponentielle comme 2? ou 10? lorsque n devient suffisamment grand.

Elle entraîne rapidement un dépassement de capacité dans les types numériques ordinaires.

Par exemple, un entier signé de 32 bits ne peut représenter correctement les factorielles que jusqu'à :

12! = 479001600

car :

13! = 6227020800

dépasse sa valeur maximale.

Un entier signé de 64 bits peut représenter exactement les factorielles jusqu'à :

20!

mais pas :

21!

Pour calculer des factorielles plus importantes, il faut employer un type multiprécision comme BigInteger.

Les permutations

Une permutation est un arrangement ordonné de tous les éléments d'un ensemble.

Deux arrangements sont considérés comme différents lorsque l'ordre de leurs éléments est différent.

Par exemple, les permutations des trois lettres A, B et C sont :

ABC
ACB
BAC
BCA
CAB
CBA

Il existe donc 6 ordres possibles.

Comme :

3! = 6

le nombre de permutations de trois éléments distincts correspond bien à la factorielle de 3.

Nombre de permutations de n éléments

Pour n éléments distincts, le nombre de permutations possibles est :

P(n) = n!

Cette formule peut être expliquée à l'aide du principe multiplicatif.

Pour la première position, il existe n choix possibles.

Après avoir sélectionné le premier élément, il reste :

n - 1

choix pour la deuxième position.

Il reste ensuite :

Après avoir sélectionné le premier élément, il reste :

n - 2

choix pour la troisième position, et ainsi de suite.

Le nombre total d'arrangements est donc :

n × (n - 1) × (n - 2) × ... × 1

soit :

n!

Exemple de permutations

Supposons que quatre personnes doivent prendre place sur quatre sièges.

Pour le premier siège, quatre personnes peuvent être choisies.

Pour le deuxième siège, il reste trois possibilités.

Pour le troisième siège, il reste deux possibilités.

Pour le dernier siège, une seule personne demeure.

Le nombre total d'ordres est donc :

4 × 3 × 2 × 1

soit :

4! = 24

Il existe donc 24 façons différentes de placer les quatre personnes.

Permutations partielles

Il n'est pas toujours nécessaire d'utiliser tous les éléments disponibles.

Une permutation partielle, également appelée arrangement, consiste à choisir et à ordonner r éléments parmi un ensemble de n éléments distincts.

Le nombre d'arrangements est donné par :

P(n,r) = n! / (n-r)!

où :

Par exemple, si l'on souhaite attribuer les trois premières positions d'une compétition à trois personnes parmi dix participants :

P(10,3) = 10! / 7!

En simplifiant :

P(10,3) = 10 × 9 × 8

Le résultat est :

720

Il existe donc 720 podiums différents.

Différence entre permutation et combinaison

Dans une permutation, l'ordre est important.

Ainsi :

ABC

et :

BAC

sont considérés comme deux résultats différents.

Dans une combinaison, l'ordre n'est pas important. Les groupes :

ABC

et :

BAC

représentent alors la même sélection.

Opération Sélection Ordre important
Permutation complète Tous les éléments Oui
Arrangement Une partie des éléments Oui

Combinaison Une partie des éléments Non

Cette distinction est fondamentale dans la résolution des problèmes de dénombrement.

Permutations avec répétition autorisée

Lorsque les éléments peuvent être réutilisés, chaque position dispose du même nombre de choix.

Si une séquence contient r positions et que chaque position peut recevoir l'une des n valeurs possibles, le nombre de séquences est :

nr

Par exemple, un code de quatre chiffres utilisant les valeurs de 0 à 9 peut produire :

104 = 10000

codes différents, lorsque les répétitions sont autorisées.

Les codes comprennent alors toutes les valeurs de :

0000

à :

9999

Il s'agit de séquences ordonnées avec répétition, et non de permutations classiques sans répétition.

Permutations d'éléments identiques

Lorsque certains éléments sont identiques, la formule n! compte plusieurs fois les mêmes arrangements.

Le nombre de permutations distinctes devient :

n! / (n1! × n2! × ... × nk!)

où :

Par exemple, le mot :

MAMAN

contient cinq lettres, avec :

Le nombre de permutations distinctes est :

5! / (2! × 2!)

soit :

120 / 4 = 30

Il existe donc 30 arrangements distincts des lettres du mot «MAMAN».

Permutations circulaires

Une permutation circulaire organise les éléments autour d'un cercle.

Dans ce cas, les arrangements obtenus uniquement par rotation sont considérés comme identiques.

Pour n éléments distincts, le nombre de permutations circulaires est :

(n - 1)!

Par exemple, quatre personnes placées autour d'une table ronde peuvent être organisées de :

(4 - 1)! = 3! = 6

façons différentes.

Dans une disposition linéaire, il aurait existé :

4! = 24

arrangements.

Cette différence vient du fait qu'une rotation complète autour de la table ne crée pas un nouvel ordre relatif entre les personnes.

Génération des permutations

Un programme peut générer toutes les permutations d'un ensemble en choisissant successivement chacun des éléments disponibles.

Une approche récursive consiste à :

Un algorithme simplifié est le suivant :

MODULE GenererPermutations(tableau, position)

   SI position = longueur(tableau) ALORS
      AFFICHER tableau
      RETOURNER
   FIN SI

   POUR i ← position JUSQU'A longueur(tableau) - 1

   ÉCHANGER tableau[position] ET tableau[i]
   GenererPermutations(tableau, position + 1)
   ÉCHANGER tableau[position] ET tableau[i]

   FIN POUR

Le deuxième échange rétablit le tableau dans son état précédent. Cette opération est appelée retour arrière ou backtracking.

Exemple de génération en Java

L'exemple suivant affiche toutes les permutations d'un tableau de caractères :

  1. public class PermutationsSample {
  2.  
  3.     public static void permuter(
  4.         char[] valeurs,
  5.         int position
  6.     ) {
  7.         if (position == valeurs.length) {
  8.             System.out.println(
  9.                 new String(valeurs)
  10.             );
  11.             return;
  12.         }
  13.  
  14.         for (
  15.             int i = position;
  16.             i < valeurs.length;
  17.             i++
  18.         ) {
  19.             echanger(valeurs, position, i);
  20.  
  21.             permuter(valeurs, position + 1);
  22.  
  23.             echanger(valeurs, position, i);
  24.         }
  25.     }
  26.  
  27.     private static void echanger(
  28.         char[] valeurs,
  29.         int a,
  30.         int b
  31.     ) {
  32.         char temporaire = valeurs[a];
  33.         valeurs[a] = valeurs[b];
  34.         valeurs[b] = temporaire;
  35.     }
  36.  
  37.     public static void main(String[] args) {
  38.         char[] valeurs = {'A', 'B', 'C'};
  39.  
  40.         permuter(valeurs, 0);
  41.     }
  42. }

Le programme produit :

ABC
ACB
BAC
BCA
CBA
CAB

L'ordre exact d'affichage dépend de la manière dont les échanges sont effectués.

Complexité de la génération des permutations

La génération de toutes les permutations de n éléments nécessite de produire n! résultats.

La complexité temporelle ne peut donc pas être inférieure à :

O(n!)

Si chaque permutation doit être copiée ou affichée, son traitement nécessite également jusqu'à n opérations. La complexité totale peut alors être exprimée par :

O(n × n!)

Cette croissance devient rapidement considérable.

Nombre d'éléments Nombre de permutations
5 120
8 40 320
10 3 628 800
12 479 001 600
15 1 307 674 368 000
20 2 432 902 008 176 640 000

Un programme peut facilement générer les permutations de cinq ou huit éléments. En revanche, parcourir toutes les permutations de vingt éléments est irréaliste dans la plupart des environnements informatiques.

Algorithmes de complexité factorielle

Certains problèmes sont naturellement associés à une complexité factorielle.

Par exemple, une méthode naïve permettant de résoudre le problème du voyageur de commerce peut examiner toutes les permutations des villes afin de trouver le trajet le plus court.

Pour n villes, le nombre de circuits possibles augmente approximativement comme :

n!

De même, un programme de recherche exhaustive peut examiner toutes les façons :

Les algorithmes factoriels sont généralement utilisables uniquement avec de très petites valeurs de n.

Approximation de Stirling

Pour les grandes valeurs de n, le calcul exact de la factorielle peut être remplacé par une approximation.

L'approximation de Stirling est :

n! ≈ √(2πn) × (n/e)n

où :

Cette approximation devient de plus en plus précise lorsque n augmente.

Elle est particulièrement utile pour :

Nombre de chiffres d'une factorielle

Le nombre de chiffres décimaux de n! peut être obtenu sans calculer directement toute la factorielle.

La formule est :

⌊log10(n!)⌋ + 1

Comme :

log(n!) =
log(1) + log(2) + ... + log(n)

il est possible de calculer :

⌊∑i=1n log10(i)⌋ + 1

Cette méthode évite de manipuler directement un entier gigantesque.

Par exemple :

10! = 3628800

possède :

7

chiffres.

Factorielle et fonction Gamma

La factorielle est normalement définie pour les entiers naturels. Elle peut toutefois être généralisée aux nombres réels et complexes à l'aide de la fonction Gamma.

La relation est :

n! = Γ(n + 1)

Par exemple :

Γ(6) = 5! = 120

La fonction Gamma permet donc de prolonger la notion de factorielle à des valeurs non entières, à l'exception de certains nombres négatifs.

Elle est utilisée en probabilités, en statistiques, en physique mathématique et dans plusieurs bibliothèques scientifiques.

Applications

Les permutations et les factorielles interviennent dans de nombreux domaines :

Elles sont également utilisées dans les coefficients binomiaux, les distributions de probabilités et les formules de dénombrement.

Avantages

Les permutations et les factorielles présentent plusieurs avantages :

Limites et précautions

Plusieurs précautions doivent néanmoins être prises :

Remarque

Les permutations et les factorielles permettent de mesurer le nombre de façons différentes d'organiser des éléments et d'évaluer la taille d'un espace de recherche. Elles montrent également qu'un problème apparemment simple peut devenir extrêmement difficile lorsque le nombre de données augmente. Une croissance en n! dépasse rapidement les capacités pratiques d'un ordinateur, ce qui oblige les programmeurs à utiliser des méthodes d'optimisation, des heuristiques, de la programmation dynamique ou des techniques de réduction de l'espace de recherche. Ces notions constituent une préparation essentielle à l'étude des coefficients binomiaux, des combinaisons, des probabilités et de l'analyse de la complexité des algorithmes.



Dernière mise à jour : Jeudi, le 16 juillet 2026