Les algorithmes, les structures de données et la complexité sont des concepts fondamentaux en informatique, essentiels pour concevoir des systèmes performants et efficaces. Que vous soyez étudiant, professionnel en développement logiciel ou passionné par l’informatique, comprendre ces notions est crucial pour résoudre des problèmes complexes et optimiser les performances des applications. Dans cet article, nous vous proposons un QCM (Questionnaire à Choix Multiples) couvrant ces trois domaines clés. À travers ce test, vous pourrez évaluer vos connaissances en matière de conception d’algorithmes, de choix de structures de données appropriées et d’analyse de la complexité des algorithmes. Que vous soyez débutant ou confirmé, ce QCM vous aidera à tester vos compétences et à améliorer votre compréhension de ces concepts fondamentaux.
1. Quelle est la complexité en temps du code suivant ?
int example(int n) {
if (n == 1) {
return 1;
}
return n * example(n - 1);
}
A O(1)
B O(n)
C O(n log n)
D O(n²)
B
Le code réalise une récursion linéaire, c’est-à-dire qu’il effectue un appel pour chaque valeur de n jusqu’à ce que n=1. Cela donne une complexité de O(n).
2. Que signifie la complexité O(1) dans un algorithme ?
A L’algorithme a une complexité qui dépend du nombre d’éléments traités.
B L’algorithme exécute un nombre constant d’opérations, quel que soit la taille de l’entrée.
C L’algorithme est linéaire et croît proportionnellement à la taille de l’entrée.
D L’algorithme a une complexité qui diminue au fur et à mesure que les éléments sont traités.
B
O(1) signifie que l’algorithme effectue un nombre constant d’opérations, indépendamment de la taille des données d’entrée. Cela signifie que l’exécution de l’algorithme ne varie pas en fonction de l’entrée.
3. Quelle est la complexité en temps du code suivant ?
void example(int n) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i % 2 == 0 && j % 2 == 0) {
printf("%d, %d\n", i, j);
}
}
}
}
A O(n³)
B O(n)
C O(n log n)
D O(n²)
D
La première boucle s'exécute n fois et la deuxième boucle s'exécute aussi n fois. Même si la condition dans la deuxième boucle limite les itérations à environ la moitié des valeurs de j, cela ne modifie pas la complexité en termes d'ordre de grandeur. La complexité reste O(n²).
4. Quel est l'algorithme qui permet de résoudre le problème du sac à dos (Knapsack) ?
A Recherche binaire
B Programmation dynamique
C Tri fusion
D Tri à bulles
B
Le problème du sac à dos est un problème d'optimisation combinatoire qui peut être résolu efficacement en utilisant la programmation dynamique. L'algorithme de programmation dynamique permet de résoudre le problème en construisant progressivement une solution optimale en utilisant les résultats des sous-problèmes.
5. Quelle est la différence entre une liste chaînée simple et une liste chaînée double ?
A Une liste chaînée simple contient un seul pointeur vers le nœud suivant, tandis qu'une liste chaînée double contient un pointeur vers le nœud suivant et un pointeur vers le nœud précédent.
B Une liste chaînée simple contient un pointeur vers un tableau, tandis qu'une liste chaînée double contient un pointeur vers un arbre.
C Une liste chaînée double est plus rapide que la simple, quelle que soit la situation.
D Il n'y a aucune différence; les deux structures fonctionnent de la même manière.
A
Une liste chaînée simple n'a qu'un seul pointeur dans chaque nœud, pointant vers le nœud suivant. En revanche, une liste chaînée double contient deux pointeurs par nœud : un pointeur vers le nœud suivant et un autre vers le nœud précédent, ce qui permet une navigation dans les deux sens.
6. Quelle est la complexité en temps du code suivant ?
void example(int n) {
for (int i = 0; i < n; i++) {
printf("%d\n", i);
}
for (int j = 0; j < n; j++) {
printf("%d\n", j);
}
}
A O(n³)
B O(n)
C O(n log n)
D O(n²)
B
Les deux boucles s'exécutent chacune n fois. Elles ne sont pas imbriquées, donc la complexité totale est O(n + n) = O(2n). Cependant, en termes de complexité asymptotique, la constante est ignorée, donc la complexité est O(n).
7. Quel est l'algorithme utilisé pour résoudre le problème du plus court chemin dans un graphe avec des poids négatifs ?
A Dijkstra
B A* (A-star)
C Floyd-Warshall
D Bellman-Ford
D
L'algorithme de Bellman-Ford est utilisé pour trouver le plus court chemin dans un graphe avec des poids négatifs. Il est plus lent que Dijkstra, mais il peut traiter des graphes avec des poids négatifs, contrairement à Dijkstra qui ne peut pas gérer cela.
8. Quelle est la complexité en temps du code suivant ?
void example(int n) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) {
printf("%d, %d\n", i, j);
}
}
}
}
A O(n³)
B O(n)
C O(n log n)
D O(n²)
D
La première boucle s'exécute n fois et la deuxième boucle s'exécute également n fois. Comme les boucles sont imbriquées, la complexité totale est O(n × n) = O(n²), indépendamment de la condition i==j.
9. Quelle est la complexité temporelle de l'algorithme de recherche dans une table de hachage ?
A O(1)
B O(n)
C O(n log n)
D O(n²)
A
La recherche dans une table de hachage se fait généralement en temps constant O(1), car elle utilise une fonction de hachage pour accéder directement à la position de l'élément. Toutefois, dans le cas de collisions, la complexité peut être affectée.
10. Quelle est la principale caractéristique des algorithmes de tri en place ?
A Ils nécessitent de la mémoire supplémentaire pour stocker les éléments triés.
B Ils modifient l'ordre des éléments dans le tableau ou la liste sans utiliser d'espace mémoire supplémentaire significatif.
C Ils sont plus rapides que les autres algorithmes de tri.
D Ils fonctionnent uniquement sur des structures de données comme les tableaux à une dimension.
B
Un algorithme de tri en place trie les éléments directement dans la structure de données existante sans nécessiter d'espace mémoire supplémentaire. Des exemples incluent le tri à bulles, le tri rapide et le tri par insertion.