Algorithmique : diviser pour régner, programmation dynamique, recherche textuelle : fiche de révision
Tri fusion et recherche dichotomique, mémoïsation et programmation dynamique (rendu de monnaie, sac à dos), algorithme de Boyer-Moore : les méthodes algorithmiques de Terminale avec leurs complexités.
1Diviser pour régner
La méthode « diviser pour régner » découpe un problème en sous-problèmes de même nature mais plus petits, les résout récursivement, puis combine les résultats. La recherche dichotomique dans un tableau trié en est l'exemple le plus simple : on compare à l'élément central, on élimine une moitié, on recommence ; chaque étape divise la taille par 2, d'où une complexité en O(log n) contre O(n) pour une recherche séquentielle.
Le tri fusion découpe le tableau en deux moitiés, les trie récursivement, puis fusionne les deux moitiés triées en un tableau trié (la fusion parcourt les deux moitiés en parallèle en prenant à chaque fois le plus petit). Complexité O(n log n) dans tous les cas, bien meilleure que les tris par insertion ou sélection en O(n²) de Première.
def tri_fusion(t):
if len(t) <= 1: return t
m = len(t) // 2
return fusion(tri_fusion(t[:m]), tri_fusion(t[m:]))
La fonction fusion(a, b) construit le résultat avec deux indices i et j : tant que les deux listes ont des éléments, elle ajoute le plus petit de a[i] et b[j] et avance l'indice correspondant, puis recopie le reste. Justification de la complexité : log₂(n) niveaux de découpage, et un travail total en O(n) par niveau pour les fusions.
2Programmation dynamique
Quand les sous-problèmes se recoupent (le même sous-problème est demandé plusieurs fois), la récursivité naïve explose. La programmation dynamique consiste à ne résoudre chaque sous-problème qu'une fois : soit en mémoïsant (dictionnaire des résultats, approche descendante), soit en remplissant un tableau des plus petits sous-problèmes vers le problème complet (approche ascendante).
Exemple canonique : le rendu de monnaie avec le nombre minimal de pièces. Pour un montant m et des pièces p, nb(m) = 1 + min(nb(m − p) pour chaque pièce p ≤ m), avec nb(0) = 0. L'approche gloutonne (prendre toujours la plus grosse pièce) échoue avec certains systèmes de pièces (par exemple {1, 3, 4} pour 6 : glouton donne 4+1+1, optimal 3+3) ; la programmation dynamique garantit l'optimum.
Autres exemples au programme : la suite de Fibonacci, le problème du sac à dos (choisir des objets de poids et valeurs donnés sans dépasser une capacité, avec un tableau à deux dimensions objet × capacité), l'alignement de séquences. La méthode se reconnaît à une relation de récurrence entre solutions optimales de sous-problèmes.
3Recherche textuelle : Boyer-Moore
Chercher un motif de longueur m dans un texte de longueur n. L'algorithme naïf teste chaque position du texte en comparant caractère par caractère : O(n × m) dans le pire cas. L'algorithme de Boyer-Moore (version de Horspool au programme) compare le motif en partant de sa FIN, et, en cas d'échec, décale le motif d'un nombre de positions calculé à l'avance grâce à une table des derniers positions de chaque caractère dans le motif (règle du mauvais caractère).
Principe du décalage : si le caractère du texte aligné sur la fin du motif n'apparaît pas dans le motif, on saute de m positions d'un coup ; s'il y apparaît, on décale pour aligner sa dernière occurrence. Sur un texte réel, beaucoup de positions sont sautées sans être examinées : en pratique l'algorithme est sous-linéaire (plus le motif est long, plus il est rapide), même si le pire cas théorique reste en O(n × m).
Exemple : chercher « NSI » dans « BAC DE NSI ». On aligne le motif aux positions 0-2, on compare la dernière lettre I au caractère C du texte : C n'est pas dans le motif, on décale de 3 ; et ainsi de suite jusqu'à trouver l'occurrence. Au bac, on demande de dérouler quelques étapes en indiquant les comparaisons effectuées et les décalages.
4Exercice type et pièges
Énoncé type : « Écrire une fonction récursive qui renvoie le nombre minimal de pièces pour rendre un montant m avec les pièces [1, 2, 5, 10], puis expliquer pourquoi la mémoïsation la rend efficace. »
def nb_pieces(m, memo={}):
if m == 0: return 0
if m in memo: return memo[m]
meilleur = float('inf')
for p in [1, 2, 5, 10]:
if p <= m: meilleur = min(meilleur, 1 + nb_pieces(m - p, memo))
memo[m] = meilleur
return meilleur
Pièges : appliquer la dichotomie sur un tableau non trié ; oublier le cas de base d'une découpe (tableau de taille 0 ou 1) ; confondre glouton et programmation dynamique ; dans Boyer-Moore, comparer depuis le début du motif ; croire que O(n log n) est toujours meilleur que O(n²) pour de très petits tableaux (les constantes comptent, mais au bac on raisonne asymptotiquement).
Définitions à connaître par cœur
Quiz : teste-toi sur algorithmique : diviser pour régner, programmation dynamique, recherche textuelle
8 questions corrigées. Réponds avant d'ouvrir la correction !
1. Quelle est la complexité du tri fusion ?
- A.O(n)
- B.O(n log n)
- C.O(n²)
- D.O(log n)
Voir la réponse
Réponse : B. O(n log n)
log₂(n) niveaux de découpage, chacun coûtant O(n) pour les fusions : O(n log n) dans tous les cas.
2. La recherche dichotomique exige que le tableau soit…
- A.non vide
- B.trié
- C.de taille paire
- D.sans doublons
Voir la réponse
Réponse : B. trié
Éliminer une moitié à chaque étape n'est correct que si les éléments sont ordonnés.
3. Avec les pièces {1, 3, 4}, combien de pièces l'algorithme glouton rend-il pour 6 ? Et l'optimum ?
- A.2 et 2
- B.3 et 2
- C.2 et 3
- D.3 et 3
Voir la réponse
Réponse : B. 3 et 2
Glouton : 4 + 1 + 1 = 3 pièces ; optimum : 3 + 3 = 2 pièces. Le glouton n'est pas optimal pour ce système.
4. Qu'est-ce que la mémoïsation ?
- A.Une méthode de tri
- B.Le stockage des résultats déjà calculés pour éviter de les recalculer
- C.Une technique de compression
- D.Une variante de la dichotomie
Voir la réponse
Réponse : B. Le stockage des résultats déjà calculés pour éviter de les recalculer
En conservant chaque résultat dans un dictionnaire, chaque sous-problème n'est résolu qu'une fois.
5. Dans Boyer-Moore, la comparaison du motif commence…
- A.par le premier caractère du motif
- B.par le dernier caractère du motif
- C.par le milieu du motif
- D.par le premier caractère du texte
Voir la réponse
Réponse : B. par le dernier caractère du motif
Comparer depuis la fin permet, en cas d'échec, de décaler le motif de plusieurs positions d'un coup.
6. Si le caractère du texte aligné sur la fin du motif n'apparaît pas dans le motif (longueur m), de combien décale-t-on ?
- A.1
- B.m − 1
- C.m
- D.2m
Voir la réponse
Réponse : C. m
Aucune position chevauchant ce caractère ne peut convenir : on saute directement de m positions.
7. Complexité de la recherche naïve d'un motif de longueur m dans un texte de longueur n (pire cas) :
- A.O(n)
- B.O(m)
- C.O(n × m)
- D.O(n + m)
Voir la réponse
Réponse : C. O(n × m)
À chacune des n positions, on peut comparer jusqu'à m caractères avant d'échouer.
8. Quelle structure de sous-problèmes caractérise la programmation dynamique ?
- A.Des sous-problèmes indépendants
- B.Des sous-problèmes qui se recoupent
- C.Un seul sous-problème
- D.Des sous-problèmes de taille identique
Voir la réponse
Réponse : B. Des sous-problèmes qui se recoupent
C'est le recouvrement qui rend la mémoïsation utile ; diviser pour régner traite des sous-problèmes indépendants.
Questions fréquentes
Diviser pour régner ou programmation dynamique : comment choisir ?
Si les sous-problèmes sont indépendants (chaque moitié d'un tableau à trier), diviser pour régner ; s'ils se recoupent (le même montant demandé par plusieurs chemins dans le rendu de monnaie), programmation dynamique.
Pourquoi le tri fusion est-il meilleur que le tri par insertion ?
O(n log n) contre O(n²) : pour un million d'éléments, environ 20 millions d'opérations contre mille milliards. Le tri par insertion reste acceptable pour de très petits tableaux ou des données presque triées.
Faut-il connaître la version complète de Boyer-Moore ?
Le programme se limite à la règle du mauvais caractère (version Horspool) : comparer depuis la fin et décaler selon la dernière occurrence du caractère dans le motif. La règle du bon suffixe est hors programme.
Que demande l'épreuve pratique sur ce chapitre ?
Souvent : implémenter la recherche dichotomique ou la fusion de deux listes triées, compléter une fonction de programmation dynamique avec son tableau, ou écrire la recherche naïve d'un motif.
