From 922703999f38ec16f037a170ad7c2bb1aa9d14cf Mon Sep 17 00:00:00 2001 From: Ryad MEHIRI Date: Wed, 21 Oct 2026 10:55:53 +0200 Subject: [PATCH] =?UTF-8?q?F5=20:=20meilleure=20p=C3=A9riode=20en=20un=20s?= =?UTF-8?q?eul=20parcours=20(O(J=C2=B3)=20=E2=86=92=20O(J))?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit La triple boucle recalculait la somme de chaque période (i, j) : J(J+1)(J+2)/6 = 167 millions d'additions pour 1 000 jours. Avec les sommes préfixes, la meilleure période finissant au jour j commence juste après le plus petit préfixe vu jusque-là : un seul parcours suffit. En gardant le premier minimum et en ne remplaçant le meilleur que s'il est strictement dépassé, on retrouve la même période que l'original en cas d'égalité (vérifié sur 200 000 tableaux aléatoires). Temps (-O2) : 0,25 s → 0,10 s. Empreinte inchangée (ff68d260a7a58441). Co-Authored-By: Claude Opus 5.5 --- banque.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/banque.c b/banque.c index 8e4be4f..3b030e6 100644 --- a/banque.c +++ b/banque.c @@ -127,21 +127,28 @@ void total_par_jour(const Transaction *t, int n, long *totaux) } /* F5 : période de jours consécutifs dont la somme des soldes est maximale */ +/* Avec prefixe(j) = totaux[0] + ... + totaux[j-1], la somme des jours i à j + * vaut prefixe(j+1) - prefixe(i). Pour chaque fin j, le meilleur début est + * donc l'indice du plus petit prefixe(i), i <= j. On garde le premier minimum + * et on ne remplace le meilleur que s'il est strictement dépassé : on obtient + * la même période que la triple boucle d'origine, même en cas d'égalité. */ long meilleure_periode(const long *totaux, int nb_jours, int *debut, int *fin) { long meilleur = totaux[0]; + long prefixe = 0, prefixe_min = 0; + int debut_min = 0; *debut = 0; *fin = 0; - for (int i = 0; i < nb_jours; i++) { - for (int j = i; j < nb_jours; j++) { - long somme = 0; - for (int k = i; k <= j; k++) - somme += totaux[k]; - if (somme > meilleur) { - meilleur = somme; - *debut = i; - *fin = j; - } + for (int j = 0; j < nb_jours; j++) { + if (prefixe < prefixe_min) { /* prefixe vaut ici prefixe(j) */ + prefixe_min = prefixe; + debut_min = j; + } + prefixe += totaux[j]; /* prefixe vaut maintenant prefixe(j+1) */ + if (prefixe - prefixe_min > meilleur) { + meilleur = prefixe - prefixe_min; + *debut = debut_min; + *fin = j; } } return meilleur;