Les entretiens pour ingénieur logiciel suivent un schéma familier dans la plupart des entreprises : un appel avec le recruteur, un ou deux tours de programmation, un tour de conception de systèmes pour les postes intermédiaires et seniors, et un tour comportemental. Vous trouverez ci-dessous 20 questions d'entretien pour ingénieur logiciel avec leurs réponses, regroupées par tour. Chaque exemple de code a été testé face à une version par force brute sur des milliers d'entrées aléatoires avant publication.
Ce que teste chaque tour
| Tour | Format habituel | Ce qu'on évalue |
|---|---|---|
| Échange avec le recruteur | 20 à 30 minutes au téléphone | Parcours, motivation, fourchette salariale, organisation |
| Programmation | 45 à 60 minutes dans un éditeur partagé | Résolution de problèmes, code propre, tests, explications pendant que vous codez |
| Fondamentaux en informatique | Intégrés à la programmation ou tour séparé | Si vous comprenez les systèmes que vous utilisez |
| Conception de systèmes | 45 à 60 minutes sur un tableau blanc ou un document | Compromis, passage à l'échelle et clarté de la communication |
| Comportemental | 30 à 45 minutes | Responsabilité, collaboration, gestion des échecs |
Les entretiens pour jeunes diplômés portent surtout sur la programmation et le comportement. Les entretiens seniors ajoutent davantage de conception de systèmes et attendent des réponses plus approfondies sur les projets passés. Pour l'échange avec le recruteur, voir nos questions d'entretien téléphonique.
Questions de programmation
Dans chaque tour de programmation, annoncez votre approche avant de taper, indiquez la complexité en temps et en mémoire, puis testez avec un petit exemple à la fin. Notre aide-mémoire Big O couvre la partie complexité.
1. Somme de deux : renvoyer les indices de deux nombres dont la somme vaut la cible
Stockez l'indice de chaque nombre dans une table de hachage. Pour chaque nouveau nombre, vérifiez si son complément est déjà dans la table.
def two_sum(nums, target):
seen = {}
for i, x in enumerate(nums):
if target - x in seen:
return [seen[target - x], i]
seen[x] = i
return []
print(two_sum([2, 7, 11, 15], 9)) # [0, 1]
Temps en O(n) et mémoire en O(n). La version par force brute teste chaque paire en O(n²). Les examinateurs veulent généralement que vous la mentionniez d'abord, puis que vous l'amélioriez.
2. Parenthèses valides : vérifier que chaque crochet est fermé dans le bon ordre
Empilez les crochets ouvrants. À chaque crochet fermant, le sommet de la pile doit être son ouvrant correspondant.
def is_valid(s):
pairs = {")": "(", "]": "[", "}": "{"}
stack = []
for ch in s:
if ch in pairs:
if not stack or stack.pop() != pairs[ch]:
return False
else:
stack.append(ch)
return not stack
print(is_valid("([]{})"), is_valid("(]")) # True False
Temps en O(n) et mémoire en O(n). La dernière ligne compte : une chaîne comme « (( » laisse des éléments dans la pile et n'est pas valide.
3. Fusionner les intervalles qui se chevauchent
Triez par heure de début, puis soit prolongez le dernier intervalle fusionné, soit commencez-en un nouveau.
def merge_intervals(intervals):
merged = []
for start, end in sorted(intervals):
if merged and start <= merged[-1][1]:
merged[-1][1] = max(merged[-1][1], end)
else:
merged.append([start, end])
return merged
print(merge_intervals([[1, 3], [2, 6], [8, 10], [15, 18]]))
# [[1, 6], [8, 10], [15, 18]]
Temps en O(n log n) à cause du tri. Demandez si des intervalles qui se touchent, comme [1, 2] et [2, 3], doivent être fusionnés. Cette version les fusionne.
4. Inverser une liste chaînée
Parcourez la liste une fois et faites pointer chaque nœud vers le précédent.
class ListNode:
def __init__(self, val, next=None):
self.val = val
self.next = next
def reverse_list(head):
prev = None
while head:
head.next, prev, head = prev, head, head.next
return prev
Temps en O(n) et mémoire supplémentaire en O(1). Si l'affectation multiple paraît trop astucieuse pour l'examinateur, écrivez-la en trois lignes avec une variable temporaire. Clair vaut mieux que court.
5. Renvoyer les k éléments les plus fréquents
Comptez avec une table de hachage, puis prenez les k plus grands compteurs avec un tas.
from collections import Counter
import heapq
def top_k_frequent(nums, k):
counts = Counter(nums)
return [x for x, _ in heapq.nlargest(k, counts.items(), key=lambda p: p[1])]
print(top_k_frequent([1, 1, 1, 2, 2, 3], 2)) # [1, 2]
Temps en O(n log k). Une question de suivi consiste à utiliser un tri par paquets sur la fréquence, qui donne O(n).
6. Concevoir un cache LRU avec get et put en O(1)
Il faut une recherche rapide et un réordonnancement rapide selon l'utilisation récente. Une table de hachage plus une liste doublement chaînée font les deux. En Python, OrderedDict est exactement cette combinaison.
from collections import OrderedDict
class LRUCache:
def __init__(self, capacity):
self.capacity = capacity
self.data = OrderedDict()
def get(self, key):
if key not in self.data:
return -1
self.data.move_to_end(key)
return self.data[key]
def put(self, key, value):
if key in self.data:
self.data.move_to_end(key)
self.data[key] = value
if len(self.data) > self.capacity:
self.data.popitem(last=False)
Certains examinateurs vous demanderont de construire vous-même la liste chaînée. Expliquez d'abord la structure : la table pointe vers les nœuds de la liste, le nœud le plus récent se trouve à une extrémité, et vous évincez depuis l'autre extrémité.
7. Plus court chemin dans une grille avec des murs
Le parcours en largeur trouve le plus court chemin lorsque chaque pas coûte la même chose.
from collections import deque
def shortest_path(grid):
rows, cols = len(grid), len(grid[0])
if grid[0][0] or grid[rows - 1][cols - 1]:
return -1
queue = deque([(0, 0, 0)])
seen = {(0, 0)}
while queue:
r, c, steps = queue.popleft()
if (r, c) == (rows - 1, cols - 1):
return steps
for dr, dc in ((1, 0), (-1, 0), (0, 1), (0, -1)):
nr, nc = r + dr, c + dc
if 0 <= nr < rows and 0 <= nc < cols and not grid[nr][nc] and (nr, nc) not in seen:
seen.add((nr, nc))
queue.append((nr, nc, steps + 1))
return -1
print(shortest_path([[0, 0, 0], [1, 1, 0], [0, 0, 0]])) # 4
Temps et mémoire en O(lignes × colonnes). Marquez les cases comme vues quand vous les ajoutez à la file, et non quand vous les retirez, sinon la même case est mise en file plusieurs fois.
8. Trouver la première version défectueuse
Les versions 1 à n sont bonnes jusqu'à un certain point, puis défectueuses. La recherche dichotomique trouve la première version défectueuse en O(log n) vérifications.
def first_bad_version(n, is_bad):
lo, hi = 1, n
while lo < hi:
mid = (lo + hi) // 2
if is_bad(mid):
hi = mid
else:
lo = mid + 1
return lo
Ce schéma s'applique à toute question oui ou non qui ne bascule qu'une fois, ce qui arrive souvent. Pour une liste de problèmes couvrant ces schémas, voir le Blind 75.
Questions de fondamentaux en informatique
9. Quelle est la différence entre un processus et un thread ?
Un processus est un programme en cours d'exécution, doté de son propre espace mémoire. Les threads s'exécutent à l'intérieur d'un processus et partagent sa mémoire. Les threads coûtent moins cher à créer et à basculer, et peuvent partager directement des données, mais ce partage est la raison pour laquelle il faut des verrous et pourquoi surviennent les situations de concurrence. Les processus sont isolés : un plantage dans l'un n'entraîne pas les autres.
10. Quelle est la différence entre TCP et UDP ?
TCP établit une connexion et garantit une livraison ordonnée et fiable, avec retransmission et contrôle de flux. UDP envoie des paquets indépendants sans garantie de livraison ni d'ordre, et avec moins de surcharge. Utilisez TCP pour les pages web, les API et les transferts de fichiers. UDP convient à la voix et à la vidéo en direct ainsi qu'aux jeux, où un paquet en retard est de toute façon inutile. Nos questions d'entretien sur les réseaux informatiques vont plus loin.
11. Que se passe-t-il quand vous tapez une URL dans un navigateur et appuyez sur Entrée ?
Le navigateur résout le nom de domaine en adresse IP grâce au DNS, ouvre une connexion TCP et effectue une négociation TLS pour le HTTPS. Il envoie une requête HTTP, et le serveur, souvent derrière un répartiteur de charge, renvoie une réponse. Le navigateur analyse le HTML, demande les CSS, le JavaScript et les images qu'il référence, puis affiche la page. Approfondissez la partie que choisit l'examinateur.
12. Comment fonctionne une table de hachage, et quelle est sa complexité en temps ?
Une fonction de hachage associe chaque clé à un casier d'un tableau. Les recherches, insertions et suppressions sont en O(1) en moyenne. Quand deux clés tombent dans le même casier, la table gère la collision par chaînage ou en sondant un autre emplacement, et elle se redimensionne lorsqu'elle est trop pleine. Le pire cas est en O(n) si beaucoup de clés entrent en collision.
13. Quand choisiriez-vous une base SQL plutôt qu'une base NoSQL ?
Choisissez SQL quand les données sont relationnelles, que vous avez besoin de jointures et de transactions, et que le schéma est assez stable : commandes, paiements, comptes utilisateurs. Choisissez un magasin de documents ou clé-valeur quand les modes d'accès sont simples, que la forme des données varie, ou que vous devez faire passer les écritures à l'échelle sur de nombreuses machines. Beaucoup de systèmes utilisent les deux. La réponse attendue par les examinateurs est le compromis, pas un gagnant. Nos questions d'entretien sur les API REST couvrent la couche API qui se trouve généralement par-dessus.
Questions de conception de systèmes
14. Concevoir un raccourcisseur d'URL
Clarifiez d'abord les exigences : combien de nouveaux liens par jour, combien de lectures, si les liens expirent, si les alias personnalisés sont autorisés. Présentez ensuite l'API (création et redirection), la manière de générer les codes courts (un compteur encodé en base 62, ou un code aléatoire avec vérification d'unicité), le stockage (un magasin clé-valeur qui associe le code à l'URL), et un cache pour les liens populaires, car les lectures sont beaucoup plus nombreuses que les écritures. Terminez par les statistiques et la prévention des abus si le temps le permet. Nous détaillons la conception complète dans notre guide de conception de systèmes.
15. Concevoir un limiteur de débit
Commencez par l'endroit où il s'exécute (à la passerelle API, par utilisateur ou par clé d'API) et par ce qui se passe quand un client dépasse la limite (HTTP 429 avec un délai avant la prochaine tentative). Le seau à jetons est le choix courant : chaque client possède un seau qui se remplit à un rythme fixe et contient un nombre maximal de jetons, et chaque requête consomme un jeton. Il permet de courtes rafales tout en imposant un débit moyen. Avec plusieurs serveurs, gardez les compteurs dans un magasin partagé comme Redis pour que chaque serveur voie le même total. Pour vous entraîner davantage, voir nos questions d'entretien sur la conception de systèmes.
Questions comportementales
Utilisez une structure claire pour chaque histoire : la situation, ce que vous avez fait, et le résultat, avec des chiffres quand vous en avez.
16. Parlez-moi de vous
Présentez en deux minutes votre parcours, qui se termine par la raison pour laquelle vous voulez ce poste. Mentionnez un ou deux projets avec des résultats concrets. Notre guide sur parlez-moi de vous contient des exemples.
17. Parlez-moi d'un bug difficile que vous avez corrigé
Exemple de réponse : « Notre service de commande commençait à expirer quelques fois par jour, sans schéma apparent. J'ai ajouté des identifiants de requête aux journaux et découvert que chaque expiration venait d'une seule requête de base de données, qui ne s'exécutait que lorsqu'un panier contenait plus de 50 articles. Il manquait un index sur la colonne de jointure. J'ai ajouté l'index, la requête lente est passée d'environ 4 secondes à moins de 50 millisecondes, et j'ai ajouté une alerte sur la latence de cette requête pour la repérer plus tôt la prochaine fois. »
18. Parlez-moi d'un désaccord avec un coéquipier
Exemple de réponse : « Un coéquipier voulait réécrire notre service de notifications dans un nouveau framework, et je trouvais le risque trop élevé avant une mise en production. Plutôt que de débattre en réunion, j'ai proposé que chacun écrive le coût et le risque. Nous avons convenu de corriger les deux pires problèmes du code actuel avant la mise en production, et de prévoir la réécriture pour le trimestre suivant. La mise en production a eu lieu à temps, et nous avons fait la réécriture deux mois plus tard avec un plan de tests complet. »
19. Parlez-moi d'un projet qui a échoué
Choisissez un échec réel dont vous étiez en partie responsable. Expliquez ce qui a mal tourné, ce que vous feriez différemment, et ce que vous avez changé ensuite. Les examinateurs vérifient l'honnêteté et la capacité à apprendre, pas un parcours sans faute.
20. Pourquoi voulez-vous travailler ici ?
Reliez un élément précis du produit ou du travail d'ingénierie de l'entreprise à votre propre expérience. « J'utilise votre API depuis deux ans et j'aimerais travailler côté plateforme » vaut mieux que « vous êtes une entreprise formidable ».
Questions à poser à l'examinateur
- À quoi ressemble une semaine type pour quelqu'un de cette équipe ?
- Comment le travail est-il planifié, et qui décide des priorités ?
- Comment fonctionnent ici la revue de code et le déploiement ?
- À quoi ressemblerait la réussite au cours des six premiers mois ?
- Quel est le problème technique le plus difficile sur lequel travaille l'équipe ?
Voir questions à poser à la fin d'un entretien pour aller plus loin.
Comment se préparer
- Choisissez un langage et utilisez-le pour chaque exercice. Python est le choix le plus courant parce que le code est court. Nos questions d'entretien Python couvrent le langage lui-même.
- Entraînez-vous par schéma plutôt que par nombre : tables de hachage, deux pointeurs, fenêtre glissante, recherche dichotomique, parcours en largeur et en profondeur, tas et programmation dynamique.
- Résolvez les problèmes à voix haute avec un minuteur. Une solution correcte mais silencieuse obtient une note inférieure à une solution claire et expliquée à voix haute.
- Entraînez-vous dans l'éditeur que vous utiliserez. Beaucoup d'entreprises utilisent CoderPad, qui propose un bac à sable gratuit.
- Préparez cinq histoires tirées de votre travail que vous pouvez adapter à la plupart des questions comportementales.
- Pour les postes intermédiaires et seniors, faites au moins quelques séances complètes de conception de systèmes avec quelqu'un qui pose des questions de relance.
Entraînez-vous aux entretiens de programmation à voix haute
YesToTheOffer transcrit vos réponses pour que vous puissiez revoir la manière dont vous avez expliqué votre solution, avec une aide au codage à partir de captures d'écran à 0.2x. 30 minutes gratuites, sans abonnement.



