← Meta Interview Insights

Meta·Machine Learning Engineer·Onsite - Coding / Algorithms·Senior

Senior
Jun 2026

Summary

Meta ML engineer interview with a set of data structures questions that covered a pretty wide range, from basic array manipulation to grid pathfinding to streaming data design. Nothing wildly unexpected but the depth expected on each one was real.

Questions Asked (4)

Q1

Given two sorted integer lists, merge them into a single sorted array. Then for a target value x, return the index of the first element greater than or equal to x (lower bound) and the index of the first element strictly greater than x (upper bound). Discuss time and space complexity, and handle duplicates and empty inputs.

Algorithms & Data Structures
Author's notes

This felt like two questions stitched together.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the problem and edge cases, then present a two-pointer merge for the sorted lists, followed by binary search for lower and upper bounds. Discuss time and space complexity, and explain how duplicates and empty inputs are handled.

Pro tip: Mention that the merge step can be skipped if the lists are already sorted and you only need bounds, but since the problem requires a merged array, do it efficiently. Also, note that Python's bisect module provides lower_bound and upper_bound, but be prepared to implement them manually.

1. Clarify requirements and edge cases

Ask about input sizes, whether lists can be empty, if duplicates are allowed, and if the merged array should be returned or just the bounds. Confirm that x can be any integer.

2. Merge two sorted lists

Use two pointers to merge the lists into a new sorted array in O(m+n) time. Handle empty lists by returning the other list.

3. Find lower and upper bounds

Implement binary search to find the first index where element >= x (lower bound) and first index where element > x (upper bound). Return -1 or len(arr) if not found, as appropriate.

4. Analyze complexity

State that merge takes O(m+n) time and O(m+n) space for the new array. Binary search takes O(log(m+n)) time and O(1) space. Overall O(m+n) time and space.

5. Handle duplicates and empty inputs

Explain that duplicates are naturally handled by binary search: lower bound returns first occurrence, upper bound returns index after last occurrence. Empty inputs: if both empty, return empty array and bounds 0; if one empty, merge returns the other.

Key Points to Mention

  • Two-pointer merge technique for sorted lists
  • Binary search for lower and upper bounds (bisect_left and bisect_right)
  • Time complexity: O(m+n) for merge, O(log(m+n)) for each binary search
  • Space complexity: O(m+n) for merged array, O(1) for binary search
  • Handling duplicates: lower bound gives first occurrence, upper bound gives after last occurrence
  • Edge cases: empty lists, x smaller than all elements, x larger than all elements

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

Q2

Implement a function that finds the minimum value in an array. Discuss different approaches and edge cases for both sorted and unsorted inputs.

Algorithms & Data Structures
Author's notes

Straightforward question.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the problem constraints (sorted vs. unsorted, array size, data types) and then discuss the trade-offs between linear scan and binary search. For unsorted arrays, a linear scan is optimal; for sorted arrays, binary search or simply taking the first element (if ascending) is better. Also cover edge cases like empty arrays, single elements, duplicates, and negative numbers.

Pro tip: Mention that in a sorted array, the minimum is at one of the ends depending on sort order, and that binary search can find it in O(log n) if the array is rotated. This shows you think beyond the obvious and consider variations.

1. Clarify requirements and constraints

Ask about input size, whether the array is sorted, if it can be empty, data types, and if there are duplicates. This ensures you handle all cases correctly.

2. Discuss approaches for unsorted arrays

Explain that a linear scan (O(n)) is optimal because you must examine each element at least once. Mention that sorting first would be O(n log n) and is unnecessary.

3. Discuss approaches for sorted arrays

For a sorted array (ascending), the minimum is the first element (O(1)). For a rotated sorted array, use binary search to find the minimum in O(log n).

4. Handle edge cases

Cover empty array (return null or throw exception), single element (return it), all duplicates, negative numbers, and large arrays (consider memory and time).

5. Implement and test

Write clean code for the chosen approach, then walk through test cases including edge cases to verify correctness.

Key Points to Mention

  • Time complexity: O(n) for unsorted, O(log n) for rotated sorted, O(1) for sorted ascending.
  • Space complexity: O(1) for iterative approaches.
  • Edge cases: empty array, single element, duplicates, negative numbers, large arrays.
  • Binary search for rotated sorted arrays: compare mid with endpoints to decide search direction.
  • Trade-offs: sorting first is inefficient; linear scan is simple and optimal for unsorted.
  • Use of built-in functions like min() in Python is acceptable but discuss implementation.

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

Q3

Given a 2D grid of open cells and walls, and a starting cell, find a path to any open cell on the boundary of the grid. Return the path as a list of coordinates. Discuss BFS vs DFS, path reconstruction, and complexity.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

I went with BFS immediately since it finds shortest path and said so upfront.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Clarify the problem constraints (grid size, movement allowed, whether diagonal moves are permitted) and then propose BFS as the optimal solution for finding the shortest path to any boundary cell. Explain the algorithm step-by-step, including how to reconstruct the path using parent pointers, and analyze time and space complexity. Finally, compare BFS with DFS, highlighting trade-offs in terms of optimality and memory usage.

Pro tip: Mention that BFS guarantees the shortest path in an unweighted grid, which is often crucial in real-world applications like robotics or game AI. Also, note that if the grid is very large, bidirectional BFS or A* with a heuristic could be more efficient, showing awareness of advanced techniques.

1. Clarify requirements and constraints

Ask about grid size, movement directions (4 or 8), whether the start cell can be on the boundary, and if multiple paths exist. Confirm that the goal is any boundary cell and that the path should be returned as a list of coordinates.

2. Choose BFS and justify

Explain that BFS explores level by level, guaranteeing the shortest path in an unweighted grid. Contrast with DFS, which may find a path but not necessarily the shortest and can get stuck in deep branches.

3. Outline BFS algorithm with path reconstruction

Describe initializing a queue with the start cell, a visited set, and a parent map. While the queue is not empty, dequeue a cell, check if it's on the boundary, and if so, reconstruct the path using the parent map. Otherwise, enqueue all valid unvisited neighbors.

4. Analyze complexity

State that time complexity is O(R*C) where R and C are grid dimensions, as each cell is visited at most once. Space complexity is also O(R*C) for the queue, visited set, and parent map in the worst case.

5. Discuss trade-offs and edge cases

Compare BFS vs DFS: BFS uses more memory but finds shortest path; DFS uses less memory but may not find shortest and can be slower in practice. Mention edge cases: start on boundary, no path exists, and large grids where bidirectional BFS or A* might be better.

Key Points to Mention

  • BFS guarantees shortest path in unweighted grids, while DFS does not.
  • Path reconstruction using a parent map or by storing paths in the queue (though the latter is less efficient).
  • Time and space complexity: O(R*C) for both, where R and C are the number of rows and columns.
  • Handling of edge cases: start on boundary, no path exists, and multiple valid paths.
  • Trade-offs: BFS uses more memory but is optimal; DFS uses less memory but may not be optimal.
  • Possible optimizations: bidirectional BFS, A* with Manhattan distance heuristic, or early termination when any boundary cell is reached.

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

Q4

Design a class that tracks a stream of numbers and returns the average of the last k values after each new value is inserted. Updates and queries should be amortized O(1), and you need to define behavior when fewer than k elements have been seen so far.

Algorithms & Data StructuresSystem Design
Author's notes

Circular buffer was the obvious move here and I said it right away.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements: define the behavior when fewer than k elements have been seen (e.g., return the average of all elements seen so far). Then, design a class using a queue (or circular buffer) to maintain the last k elements and a running sum to compute the average in O(1) time per operation. Explain how you achieve amortized O(1) by ensuring each element is added and removed at most once.

Pro tip: Mention that you would use a fixed-size circular buffer to avoid the overhead of dynamic resizing and to keep memory usage constant, which is crucial for high-throughput ML systems. Also, discuss how you would handle edge cases like k=0 or negative k gracefully.

1. Clarify requirements and edge cases

Ask about the expected behavior when fewer than k elements have been seen (e.g., return average of all seen elements or 0). Also clarify constraints: k > 0, stream size, and whether the stream can be infinite.

2. Choose data structures

Select a queue (or circular buffer) to store the last k elements and maintain a running sum. This allows O(1) insertion and removal, and O(1) average computation.

3. Design the class interface

Define methods: add(value) to insert a new number and update the sum and queue; getAverage() to return the current average. Ensure getAverage() is O(1).

4. Implement the logic

In add(value): if queue size == k, remove the oldest element and subtract it from sum. Then add the new value to queue and sum. In getAverage(): if queue is empty, return 0 (or handle as per requirement); else return sum / queue.size().

5. Analyze complexity and discuss optimizations

Explain that each element is added and removed at most once, so amortized O(1) per operation. Discuss potential optimizations like using a fixed-size array for the circular buffer to avoid dynamic memory allocation.

Key Points to Mention

  • Use of a queue or circular buffer to maintain the last k elements.
  • Maintaining a running sum to compute the average in O(1) time.
  • Handling the case when fewer than k elements have been seen (e.g., average of all elements so far).
  • Amortized O(1) time complexity: each element is enqueued and dequeued at most once.
  • Space complexity: O(k) for storing the last k elements.
  • Edge cases: k=0, negative k, empty stream, and large streams.

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