Bonjour,
correction: intersection, pas union
pendant un entretien on m'a demandé de coder un algorithme qui calculerait l'intersection d'une liste de tableaux (notons-les L1 à Ln). J'ai donné un algo relativement naïf qui calcule l'intersection de 2 tableaux puis ensuite l'intersection du résultat avec le tableau d'après dans la liste. Il m'a ensuite demandé d'en définir l'ordre de complexité, ce dont je suis pas très capable, donc j'ai répondu "N², peut-être N³".
Reprenons du début, pour la première intersection, on parcours le 2nd tableau L1 fois, donc ça donne du N² ? Donc si on continue comme ça, on fera N-1 calcul d'intersection, donc N-1 fois N² ? donc une complexité N³ ?
Ensuite il m'a demandé comment il pouvait être améliorer, j'ai dit « si on ne repasse pas par les anciennes valeurs ». Et aujourd'hui j'ai implémenté cet algo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | <?php function getIntersectionOfArrays($arrays) { $return = []; $indexes = []; //!1 foreach($arrays as &$array) { if(count($array) == 0) // if an array is empty, intersection is empty return []; sort($array); $indexes[] = 0; } $currentTesting = 1; $numberOfArray = count($arrays); //!2 while($indexes[0] < count($arrays[0])) { if($arrays[0][ $indexes[0] ] < $arrays[$currentTesting][ $indexes[ $currentTesting ] ]) { $indexes[0]++; $currentTesting = 1; } else if($arrays[0][ $indexes[0] ] > $arrays[$currentTesting][ $indexes[ $currentTesting ] ]) { $indexes[ $currentTesting ]++; if($indexes[ $currentTesting ] == count($array[ $currentTesting ])) { break; } } else { $currentTesting++; if($currentTesting == count($arrays)) { $return[] = $arrays[0][ $indexes[0] ]; $currentTesting = 1; //!3 foreach($indexes as &$index) { $index++; } } } } return $return; } |
Cet algo tient un pointeur sur chaque tableau et avance la valeur la plus faible entre celle du premier tableau et celle du tableau en cours (au début, le deuxième). Tant que les deux valeurs ne sont pas identiques, on avance la plus faible. Si elles le sont, on incrémente le tableau en cours (on compare donc le premier avec le troisième). Si elles sont toutes égales, on ajoute la valeur au tableau de retour et on avance tous les indexes. Si un des indexes dépasse de son tableau, on a fini.
Pour celui-là (ne prenons pas en compte que c'est en PHP et que array() est un faux tableau, où que j'appelle count() à chaque tour de boucle), j'imagine qu'en !1 ça donne du N×NlogN (si on considère sort comme un quicksort), donc ça donne N²logN donc N² ? Ensuite pour !2, on va parcourir chaque tableau linéairement, donc encore une fois, celà est-il bien N² ? Pour !3, étant fait seulement quand une certaine condition est respectée (toutes les valeurs identiques), c'est juste du N ? Dois-je en conclure que mon algo est en N² ? ou je me suis trompé quelque part ?
Merci.