diff --git a/banque b/banque index 68876ea..55060bc 100755 Binary files a/banque and b/banque differ diff --git a/banque.c b/banque.c index 7f555e9..42dc709 100644 --- a/banque.c +++ b/banque.c @@ -88,28 +88,29 @@ void trier_par_montant(Transaction *t, int n) /* F2 : nombre de clients ayant au moins une transaction */ int nb_clients_distincts(const Transaction *t, int n) { - int clients_vus[NB_CLIENTS] = {0}; int nb = 0; - for (int i = 0; i < n; i++) { - int client = t[i].client; - if (!clients_vus[client]) { - clients_vus[client] = 1; - nb++; + int deja_vu = 0; + for (int j = 0; j < i; j++) { + if (t[j].client == t[i].client) { + deja_vu = 1; + break; + } } + if (!deja_vu) + nb++; } - return nb; } -/* F3 : solde total de chaque client */ +/* F3 : solde total de chaque client en O(n + c) */ void total_par_client(const Transaction *t, int n, long *totaux) { for (int c = 0; c < NB_CLIENTS; c++) { totaux[c] = 0; - for (int i = 0; i < n; i++) - if (t[i].client == c) - totaux[c] += t[i].montant; + } + for (int i = 0; i < n; i++) { + totaux[t[i].client] += t[i].montant; } } @@ -118,30 +119,36 @@ void total_par_jour(const Transaction *t, int n, long *totaux) { for (int j = 0; j < NB_JOURS; j++) { totaux[j] = 0; + for (int i = 0; i < n; i++) + if (t[i].jour == j) + totaux[j] += t[i].montant; } - - for (int i = 0; i < n; i++) - totaux[t[i].jour] += t[i].montant; } -/* F5 : période de jours consécutifs dont la somme des soldes est maximale */ +/* F5 : période de jours consécutifs dont la somme des soldes est maximale en O(J) */ long meilleure_periode(const long *totaux, int nb_jours, int *debut, int *fin) { long meilleur = totaux[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; - } + + long somme_courante = totaux[0]; + int debut_courant = 0; + + for (int j = 1; j < nb_jours; j++) { + if (somme_courante < 0) { + somme_courante = totaux[j]; + debut_courant = j; + } else { + somme_courante += totaux[j]; + } + if (somme_courante > meilleur) { + meilleur = somme_courante; + *debut = debut_courant; + *fin = j; } } + return meilleur; } @@ -155,13 +162,45 @@ const Transaction *rechercher_par_id(const Transaction *t, int n, int id) } /* F7 : nombre de paires de transactions de montants opposés (a + b = 0) */ + + +static int cmp_long(const void *a, const void *b) +{ + long x = *(const long *)a; + long y = *(const long *)b; + return (x > y) - (x < y); +} + long nb_paires_opposees(const Transaction *t, int n) { + /* 1. Copier et trier les montants : O(n log n) */ + long *m = malloc(n * sizeof(long)); + for (int i = 0; i < n; i++) { + m[i] = t[i].montant; + } + qsort(m, n, sizeof(long), cmp_long); + + /* 2. Deux pointeurs : O(n) au lieu de O(n²) */ long nb = 0; - for (int i = 0; i < n; i++) - for (int j = i + 1; j < n; j++) - if (t[i].montant + t[j].montant == 0) + int g = 0, d = n - 1; + + while (g < d) { + long somme = m[g] + m[d]; + + if (somme < 0) { + g++; + } else if (somme > 0) { + d--; + } else { + /* somme == 0 : on compte tous les m[d] identiques en face de m[g] */ + for (int k = d; k > g && m[k] == m[d]; k--) { nb++; + } + g++; /* Puis on passe simplement au m[g] suivant ! */ + } + } + + free(m); return nb; }