Nextdoor Software Engineer Interview Questions
18+ questions from real Nextdoor Software Engineer interviews, reported by candidates.
Round Types
Top Topics
Questions
Nextdoor Full-Time SDE Tech Phone Screen Interview Questions
The niche Nextdoor Coding: Print comments Merge interval with start and end time in format like Monday 12:30, Tuesday 17:20 Design: Design a jenkins like job scheduling system
#56 Merge Intervals
LeetCode #56: Merge Intervals. Difficulty: Medium. Topics: Array, Sorting. Asked at Nextdoor in the last 6 months.
#165 Compare Version Numbers
LeetCode #165: Compare Version Numbers. Difficulty: Medium. Topics: Two Pointers, String. Asked at Nextdoor in the last 6 months.
## Problem Given a flat list of comment objects (each with an id and optional parent_id), reconstruct the nested tree structure and implement depth-first traversal for rendering. ```python from dataclasses import dataclass, field from typing import Optional @dataclass class Comment: id: int author: str body: str parent_id: Optional[int] children: list['Comment'] = field(default_factory=list) def build_tree(comments: list[Comment]) -> list[Comment]: # Returns list of root-level comments with children populated pass def render_thread(roots: list[Comment], indent: int = 0) -> str: pass ``` **Example:** ``` comments = [ Comment(1, "alice", "First!", None), Comment(2, "bob", "Reply to first", 1), Comment(3, "carol", "Reply to bob", 2), ] build_tree(comments) -> [Comment(1, children=[Comment(2, children=[Comment(3)])])] ``` ## Follow-ups 1. What data structure makes `build_tree` run in O(n) rather than O(n^2)? 2. How would you handle orphaned comments (parent_id points to a non-existent comment)? 3. How would you sort children by score (upvotes - downvotes) at each level? 4. How would you implement lazy loading so deep sub-threads are only fetched on expand?
## Problem Compute the sum of all integers in a nested list weighted by their depth. ## Likely LeetCode equivalent LC 339 (Nested List Weight Sum) is the direct match. ## Tags binary_tree, recursion, DFS
## Problem On a mobile client, URLs often contain sensitive data in query parameters (auth tokens, user IDs, emails). Write a function that strips or masks a configurable set of parameter names before the URL is written to logs. ```kotlin // Android (Kotlin) fun desensitizeUrl( url: String, sensitiveKeys: Set<String> = setOf("token", "email", "uid", "password"), mask: String = "***" ): String ``` **Example:** ``` desensitizeUrl("https://api.example.com/user?uid=42&token=abc123&page=2") -> "https://api.example.com/user?uid=***&token=***&page=2" desensitizeUrl("https://example.com/no-params") -> "https://example.com/no-params" ``` ## Follow-ups 1. How do you handle URL-encoded parameter values (e.g., `email=user%40example.com`)? 2. What edge cases arise with repeated parameters (e.g., `tag=a&tag=b&token=x`)? 3. How would you extend this to mask sensitive path segments (e.g., `/users/{uid}/profile`)? 4. Should you mask or omit sensitive parameters entirely? What are the trade-offs for debugging?
## Problem Build a feed list component that loads items in pages from a paginated API. As the user scrolls near the bottom, the next page is automatically fetched and appended. Items already fetched should not be re-fetched. ```ts interface FeedItem { id: string; content: string; } interface FeedPage { items: FeedItem[]; nextCursor: string | null; } async function fetchPage(cursor: string | null): Promise<FeedPage> { ... } class FeedList { private items: FeedItem[] = []; private cursor: string | null = null; private loading = false; async loadMore(): Promise<void> { ... } // fetch next page onScroll(scrollTop: number, clientHeight: number, scrollHeight: number): void { ... } render(): FeedItem[] { return this.items; } } ``` **Requirement:** Prefetch the next page when the user is within 20% of the bottom. ## Follow-ups 1. How do you prevent multiple simultaneous fetches if the user scrolls rapidly? 2. How would you handle a fetch error mid-scroll gracefully (retry strategy)? 3. If items can be deleted from the feed server-side, how do you handle stale cursors? 4. How would you implement pull-to-refresh that resets the feed from the top?
## Problem In an Android-style view system, each view has an integer ID. Views can be nested in ViewGroups. Implement `findViewByIdRecursive` that searches the view tree and returns the first view matching the given ID. ```java public abstract class View { private int id; public int getId() { return id; } public View(int id) { this.id = id; } } public class ViewGroup extends View { private List<View> children = new ArrayList<>(); public void addChild(View v) { children.add(v); } public List<View> getChildren() { return children; } public ViewGroup(int id) { super(id); } } public static View findViewByIdRecursive(View root, int targetId) { ... } ``` **Example:** ``` ViewGroup root(0) -> [View(1), ViewGroup(2) -> [View(3), View(4)]] findViewByIdRecursive(root, 3) -> View(3) findViewByIdRecursive(root, 99) -> null ``` ## Follow-ups 1. DFS or BFS — which is better here, and does it matter for correctness? 2. How would you optimize repeated lookups by caching ID-to-view mappings? 3. How would you handle the case where duplicate IDs exist in the hierarchy? 4. How would you add `findAllViewsById` that returns all matching views?
## Problem Given two hashmaps (dicts) A and B, compute their difference report: keys only in A, keys only in B, keys in both but with different values, and keys in both with identical values. ```python from dataclasses import dataclass from typing import Any @dataclass class DiffReport: only_in_a: dict # key -> A[key] only_in_b: dict # key -> B[key] changed: dict # key -> (A[key], B[key]) unchanged: dict # key -> value def dict_diff(a: dict, b: dict) -> DiffReport: pass ``` **Example:** ``` a = {"x": 1, "y": 2, "z": 3} b = {"y": 99, "z": 3, "w": 4} dict_diff(a, b) -> DiffReport( only_in_a={"x": 1}, only_in_b={"w": 4}, changed={"y": (2, 99)}, unchanged={"z": 3} ) ``` ## Follow-ups 1. How do you handle nested dicts — would you diff recursively? 2. What equality check do you use for values that may be lists or objects? 3. How would you serialize the DiffReport as a human-readable patch format? 4. How would you apply a DiffReport to transform dict A into dict B?
## Problem A home feed can have thousands of posts. Rendering all DOM nodes at once causes severe performance problems. Implement a virtualized list that only renders the posts currently visible in the viewport, plus a small buffer above and below. ```js class VirtualizedFeed { constructor(container, items, itemHeight) { // container: HTMLElement // items: array of data objects // itemHeight: fixed height per item in px } render() { ... } // initial render onScroll() { ... } // called on scroll event; updates visible window updateItems(newItems) { ... } // append or prepend new items } ``` **Requirements:** Only N visible items + 5 buffer items above and below are in the DOM at any time. Scroll position must feel native. ## Follow-ups 1. How do you calculate which item indices are visible given scrollTop and containerHeight? 2. How do you maintain scroll position when prepending new items (e.g., "5 new posts") at the top? 3. How do variable-height items change the virtualization math? 4. How would you handle keyboard navigation (arrow keys) through the virtualized list?
## Problem Given a list of integers and K, partition it into exactly K non-empty contiguous subarrays. Minimize the difference between the maximum subarray sum and the minimum subarray sum across all K groups. ```python def split_integers(nums: list[int], k: int) -> tuple[list[list[int]], int]: # returns: (partition, max_sum - min_sum) pass def min_split_difference(nums: list[int], k: int) -> int: # returns: the minimum achievable difference pass ``` **Example:** ``` nums = [1, 2, 3, 4, 5], k = 2 # Best split: [1,2,3] sum=6, [4,5] sum=9 -> diff=3 # Or [1,2,3,4] sum=10, [5] sum=5 -> diff=5 min_split_difference([1,2,3,4,5], 2) -> 3 ``` ## Follow-ups 1. How does a DP formulation with states (index, groups_remaining) solve this? 2. What is the time complexity of your DP solution? 3. How would binary search on the answer simplify the problem (binary search on difference)? 4. Does the order of elements in the array matter? What if elements can be rearranged?
## Problem Implement bidirectional conversion between nested JSON and a flat dot-notation key-value format. Nested keys are joined with `.`; array indices use bracket notation. ```python def flatten_json(obj: dict, prefix: str = "") -> dict[str, str]: # {"a": {"b": 1}, "c": [2, 3]} -> {"a.b": "1", "c[0]": "2", "c[1]": "3"} pass def unflatten_json(flat: dict[str, str]) -> dict: # Reverse of flatten_json pass ``` **Example:** ``` flatten_json({"user": {"name": "Alice", "scores": [10, 20]}}) -> {"user.name": "Alice", "user.scores[0]": "10", "user.scores[1]": "20"} unflatten_json({"user.name": "Alice", "user.scores[0]": "10", "user.scores[1]": "20"}) -> {"user": {"name": "Alice", "scores": [10, 20]}} ``` ## Follow-ups 1. How do you handle key collisions when a path could be both a leaf and a subtree? 2. How do you distinguish between a string value "10" and an integer 10 in the flat format? 3. How would you extend this to support mixed arrays (arrays containing both objects and primitives)? 4. What is the maximum nesting depth your solution supports before hitting Python's recursion limit?
## Problem Return all possible letter combinations from a phone number digit string. ## Likely LeetCode equivalent LC 17 (Letter Combinations of a Phone Number) is the direct match. ## Tags backtracking, recursion, strings
## Problem Find the maximum area of an island (connected group of 1s) in a binary grid. ## Likely LeetCode equivalent LC 695 (Max Area of Island) is the direct match. ## Tags graph, DFS, matrix
## Problem Build the core logic and frontend for a card-matching memory game. An NxM grid of face-down cards hides N*M/2 pairs. Players flip two cards per turn; a match keeps them face-up, a mismatch flips them back after a short delay. ```ts type Card = { id: number; pairId: number; flipped: boolean; matched: boolean }; class MemoryGame { constructor(public readonly cards: Card[]) {} flip(cardId: number): 'wait' | 'match' | 'no_match' | 'already_flipped' { ... } get moveCount(): number { ... } get isComplete(): boolean { ... } reset(): void { ... } } function createDeck(pairs: number): Card[] { ... } // shuffles cards ``` **Requirements:** Only 2 cards can be in the "pending" state at once. Enforce a delay before non-matching cards are flipped back. ## Follow-ups 1. How do you prevent the user from clicking a third card while the mismatch delay is running? 2. How would you implement the shuffle to guarantee no card is adjacent to its pair? 3. How would you add a high-score board stored in localStorage? 4. How would you animate the flip without using external libraries (CSS 3D transform)?
## Problem Compute the sum of elements within a given range, possibly using a prefix sum array for efficient queries. ## Likely LeetCode equivalent LC 303 (Range Sum Query - Immutable) is the direct match. ## Tags arrays, prefix-sum
## Problem Given a list of participants and an exclusion list (pairs who should not be matched, e.g., couples or family members), generate a valid Secret Santa assignment where every person gives to exactly one other person, receives from exactly one person, and no exclusion is violated. ```python from typing import Optional def secret_santa( participants: list[str], exclusions: list[tuple[str, str]] # (a, b) means a must not give to b ) -> Optional[dict[str, str]]: # {giver: receiver} or None if impossible pass ``` **Example:** ``` participants = ["Alice", "Bob", "Carol", "Dave"] exclusions = [("Alice", "Bob"), ("Bob", "Alice")] # couple secret_santa(participants, exclusions) # Valid: {"Alice": "Carol", "Bob": "Dave", "Carol": "Bob", "Dave": "Alice"} ``` ## Follow-ups 1. How do you model this as a graph problem (directed Hamilton cycle with forbidden edges)? 2. When is a valid assignment impossible? Give a minimal example. 3. How would you ensure the assignment is uniformly random among all valid assignments? 4. How would you scale this to 500 participants with complex exclusion rules?
## Problem Sort or compare a list of semantic version strings (major.minor.patch) in the correct order. ## Likely LeetCode equivalent LC 165 (Compare Version Numbers) is closely related. ## Tags strings, sorting
See All 18 Nextdoor Software Engineer Questions
Full question text, answer context, and frequency data for subscribers.
Get Access