← Airbnb Interview Insights

Airbnb·Software Engineer·Onsite - Coding / Algorithms·Senior

SeniorPrefer not to say
Jun 2026

Summary

Airbnb software engineer interview that was basically a full game engine implementation problem. More involved than I expected for a coding round, they really pushed on generalization and complexity analysis.

Questions Asked (6)

Q1

Design and implement a Connect Four game engine with a 6x7 board, supporting drop(col, player), getStatus(), and reset() methods. Gravity must be enforced so discs fall to the lowest empty cell.

Algorithms & Data StructuresSystem Design
Author's notes

Spent probably too long setting up the board structure before even touching the API surface.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements and constraints, then outline the data structures (e.g., 2D array and column heights) and algorithms for drop, status check, and reset. Implement the core methods with clean code, and discuss optimizations and edge cases.

Pro tip: Mention that you would maintain a separate array of column heights to achieve O(1) drop and win-check, and discuss how to extend the design for a variable board size or AI opponent.

1. Clarify Requirements

Ask about board dimensions, win conditions, input validation, and whether the engine needs to support undo or AI. Confirm expected time/space complexity.

2. Design Data Structures

Propose a 2D array (6x7) to represent the board and an array of size 7 to track the next available row per column. Discuss trade-offs with alternative representations.

3. Implement Core Methods

Write drop(col, player) that validates the column, places the disc at the lowest empty cell, updates the column height, and checks for a win. Implement getStatus() to return win/draw/in-progress, and reset() to clear the board.

4. Optimize Win Detection

Explain how to check for a win efficiently by only examining lines through the last dropped disc (horizontal, vertical, two diagonals) rather than scanning the entire board.

5. Test and Discuss Extensions

Walk through edge cases (full column, full board, invalid input) and suggest possible extensions like variable board size, AI opponent, or persistence.

Key Points to Mention

  • Use a 2D array for the board and a separate array for column heights to achieve O(1) drop and win-check.
  • Validate input: column index within bounds, column not full, and player is valid (e.g., 1 or 2).
  • Win detection: check only the last placed disc's row, column, and diagonals for four consecutive same-player discs.
  • getStatus() should return an enum or string indicating win (with winner), draw, or in-progress.
  • reset() should clear the board and reset column heights to zero.
  • Discuss time/space complexity: O(1) for drop and win-check, O(1) for reset, O(42) space for board.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

How do you detect a win efficiently after each move, without scanning the entire board? Aim for O(k) time based only on the last placed disc.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

This is where I actually felt good.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Focus on the last placed disc and check only the four lines (horizontal, vertical, and two diagonals) passing through it. For each direction, count consecutive same-colored discs in both directions, and if the total reaches k, declare a win. This yields O(k) time because you examine at most 2k-1 discs per direction.

Pro tip: Mention that you can optimize further by precomputing directional offsets and using a single loop per direction, and note that this approach generalizes to any k-in-a-row game (e.g., Connect Four, Gomoku).

1. Identify the last move

Start by locating the coordinates (row, col) of the most recently placed disc, as only lines through this disc can form a new winning sequence.

2. Define the four directions

Consider the four axes: horizontal (0,1), vertical (1,0), diagonal (1,1), and anti-diagonal (1,-1). These cover all possible winning lines.

3. Count consecutive discs in both directions

For each direction, move stepwise from the last move in both positive and negative directions, counting consecutive discs of the same color until a different color or boundary is hit.

4. Check for win condition

If the total count (including the last disc) in any direction is at least k, return true; otherwise, continue to the next direction.

5. Analyze time and space complexity

Explain that each direction requires at most 2k-1 checks, so total time is O(k) and space is O(1), as no additional data structures are needed.

Key Points to Mention

  • Only lines passing through the last move can create a new win, so checking other cells is unnecessary.
  • The four directions cover all possible winning lines: horizontal, vertical, and two diagonals.
  • Counting in both directions from the last move ensures you capture the full sequence.
  • The algorithm runs in O(k) time because you examine at most 2k-1 discs per direction.
  • Space complexity is O(1) since you only use a few variables for counting and direction.
  • This method is efficient and can be easily extended to any board size or win length k.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

How would you handle invalid inputs like an out-of-range column, a full column, or a move from the wrong player?

API & IntegrationsAlgorithms & Data Structures
Author's notes

Pretty mechanical but they wanted explicit error types, not just a boolean.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the context: is this a library API, a service endpoint, or an internal function? Then propose a consistent error-handling strategy that validates inputs early, returns structured errors, and avoids corrupting game state. Emphasize that invalid inputs should be rejected with clear, actionable feedback rather than silently ignored or causing crashes.

Pro tip: Treat invalid inputs as part of the API contract: define error types and document them, so clients can handle them programmatically. This shows you think about robustness and developer experience, not just correctness.

1. Clarify the interface and expectations

Ask whether this is a public API, internal function, or service, and what the caller expects (exceptions, error codes, Result types). Confirm if there are existing conventions in the codebase.

2. Validate inputs early and comprehensively

Check column bounds, board fullness, and player turn before any state mutation. Use guard clauses or a validation layer to centralize checks.

3. Choose a consistent error-handling mechanism

Decide between exceptions, error codes, or Result types based on language and API style. Ensure errors are descriptive and include context (e.g., 'Column 8 out of range 0-6').

4. Ensure atomicity and state safety

Guarantee that invalid inputs do not partially mutate the game state. Validate before any changes, or use transactions/rollbacks if needed.

5. Document and test edge cases

Add unit tests for each invalid input scenario and document the error behavior in the API reference. Consider logging for observability.

Key Points to Mention

  • Input validation: bounds checking for column index, board fullness check, and player turn verification.
  • Error types: use specific exceptions or error codes (e.g., InvalidColumnError, ColumnFullError, WrongPlayerError) for programmatic handling.
  • Idempotency and atomicity: invalid inputs should not change game state; validate before mutating.
  • API design: consider returning a Result type or throwing exceptions based on language idioms and caller expectations.
  • Testing: unit tests for each invalid input, including boundary cases (e.g., column -1, column == width).
  • Observability: log invalid attempts for debugging and potential abuse detection, but avoid leaking sensitive info.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q4

Generalize the game to an MxN board with a configurable connect length k instead of hardcoded values.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

I'd already parameterized the board dimensions but forgot to thread k through the win-check logic at first.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements: the board dimensions M and N, the connect length k, and the win condition (exactly k or at least k). Then outline a generalized algorithm that checks for k consecutive pieces in all directions, and discuss how to handle edge cases and optimize for performance.

Pro tip: Mention that you would first write a brute-force solution to validate correctness, then optimize by tracking only the last move's impact, since only that move can create a new winning line. This shows you understand both correctness and efficiency.

1. Clarify requirements and constraints

Ask about the exact win condition (exactly k or at least k), whether the board can be larger than memory, and if there are time/space constraints. Confirm that k can be any positive integer up to min(M, N).

2. Design a generalized win-check algorithm

For a given move at (r, c), check all four directions (horizontal, vertical, two diagonals) by counting consecutive same-colored pieces in both directions. If the total count reaches k, the player wins.

3. Optimize the win check

Instead of scanning the entire board after each move, only check around the last placed piece. This reduces time complexity from O(M*N) per move to O(k) per move, which is efficient for large boards.

4. Handle edge cases and board representation

Consider using a 2D array or a hash map for sparse boards. Handle cases where k=1 (immediate win) or k > min(M, N) (impossible to win). Also, ensure the algorithm works for any M, N, and k.

5. Discuss trade-offs and testing

Compare time vs. space trade-offs: e.g., precomputing all possible winning lines vs. on-the-fly checking. Suggest unit tests for various board sizes and k values, including edge cases.

Key Points to Mention

  • Generalization of win condition to k consecutive pieces in any direction.
  • Efficiency: checking only around the last move reduces time complexity to O(k) per move.
  • Board representation: 2D array for dense boards, hash map for sparse boards.
  • Edge cases: k=1, k > min(M, N), and boards with M or N equal to 1.
  • Trade-offs between precomputing winning lines and dynamic checking.
  • Testing strategy: unit tests for different M, N, k, and win conditions.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q5

Discuss the trade-offs between using a 2D array versus bitboards for the board representation. What are the time and space complexity implications?

Technical Trade-offsAlgorithms & Data Structures
Author's notes

Bitboards came up and I had to be honest that I knew the concept but hadn't implemented one for Connect Four specifically.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining the two representations and their fundamental differences in memory layout and access patterns. Then compare them across key dimensions: time complexity for common operations (e.g., move generation, collision detection), space complexity, and cache performance. Finally, discuss practical trade-offs in the context of the game or application, mentioning when each is preferable.

Pro tip: Demonstrate awareness of real-world constraints: bitboards excel in performance-critical, memory-rich environments (e.g., chess engines), while 2D arrays offer simplicity and flexibility for dynamic or sparse boards. Mentioning specific examples like chess or Go shows depth.

1. Define the representations

Briefly explain what a 2D array and a bitboard are, including their memory layout (e.g., row-major vs. bit-packed) and typical use cases.

2. Compare time complexity

Analyze operations like accessing a cell, checking adjacency, generating moves, and detecting collisions. Highlight how bitboards use bitwise operations for O(1) parallel checks, while 2D arrays may require loops.

3. Compare space complexity

Discuss memory usage: 2D arrays store each cell explicitly (O(n^2) for n x n board), while bitboards pack bits (O(n^2 / word_size) words). Note overhead for multiple bitboards (e.g., one per piece type).

4. Consider practical factors

Mention cache locality, ease of implementation, flexibility for irregular boards, and language support for bitwise operations. These often outweigh theoretical complexity.

5. Conclude with trade-offs

Summarize when to choose each: bitboards for performance-critical, dense boards with fixed size; 2D arrays for simplicity, dynamic boards, or when memory is constrained.

Key Points to Mention

  • Time complexity: bitboards enable O(1) parallel operations (e.g., AND, OR, shifts) for move generation and collision detection, while 2D arrays often require O(n) or O(n^2) loops.
  • Space complexity: 2D arrays use O(n^2) space regardless of density; bitboards use O(n^2 / w) words (w = word size), but multiple bitboards (e.g., per piece type) can increase constant factors.
  • Cache performance: bitboards are compact and fit in cache, reducing memory bandwidth; 2D arrays may suffer from cache misses due to larger memory footprint.
  • Implementation complexity: 2D arrays are intuitive and easier to code; bitboards require bitwise manipulation and careful indexing, increasing development time and bug risk.
  • Flexibility: 2D arrays easily support irregular or dynamic board sizes; bitboards assume fixed-size boards and are less adaptable.
  • Use cases: bitboards are standard in chess engines for speed; 2D arrays are common in simpler games or when board size varies.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q6

What unit tests would you write for this game engine, including edge cases?

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

Rattled off the obvious ones: full column rejection, win on last cell of board, draw state, alternating turns enforced.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the game engine's core components and expected behaviors, then systematically outline unit tests for each module, emphasizing edge cases like boundary conditions, invalid inputs, and concurrency issues. Structure your answer around test categories (e.g., physics, rendering, input handling) and explain how each test isolates a unit and verifies correctness.

Pro tip: Demonstrate test-driven development (TDD) mindset by suggesting writing tests before implementation, and mention using mocks/stubs to isolate units and avoid flaky tests. Also, highlight the importance of testing deterministic behavior in game loops and handling floating-point precision edge cases.

1. Clarify Scope and Components

Ask clarifying questions about the game engine's architecture, key modules (e.g., physics, rendering, input, audio), and expected behaviors to ensure you target the right units.

2. Identify Core Units and Behaviors

List the main units (classes/functions) and their responsibilities, then define the expected input-output behavior for each to guide test design.

3. Design Tests for Normal and Edge Cases

For each unit, outline tests for typical scenarios and edge cases such as boundary values, null/empty inputs, overflow, and error conditions.

4. Address Integration and Non-Functional Aspects

Discuss tests for interactions between units (e.g., collision detection triggering events) and non-functional aspects like performance and concurrency, if relevant.

5. Prioritize and Explain Rationale

Prioritize tests based on risk and impact, and explain why certain edge cases are critical (e.g., preventing crashes or ensuring fair gameplay).

Key Points to Mention

  • Boundary conditions: testing minimum/maximum values for positions, velocities, health, etc.
  • Invalid inputs: null objects, malformed data, out-of-range parameters.
  • State transitions: testing game state changes (e.g., start, pause, game over) and ensuring correct behavior.
  • Concurrency and timing: if the engine is multithreaded, test for race conditions and deterministic behavior in game loops.
  • Mocking dependencies: use mocks/stubs for external systems (e.g., rendering, input) to isolate units.
  • Floating-point precision: test for epsilon comparisons in physics calculations to avoid flaky tests.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.