PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep

Quick Overview

This question evaluates understanding of ordered data traversal and efficient lookup design, assessing competency with data structures, indexing and reasoning about time and space complexity for repeated neighbor queries.

  • easy
  • Ziprecruiter
  • Coding & Algorithms
  • Machine Learning Engineer

Find Neighboring Records by Identifier

Company: Ziprecruiter

Role: Machine Learning Engineer

Category: Coding & Algorithms

Difficulty: easy

Interview Round: Technical Screen

You are given an ordered list of records. Each record is a dictionary-like object with a unique string field called `id` and any number of additional attributes. Implement a utility that supports the following operations: 1. `get_next_id(id: string) -> string | null` - Return the `id` of the record immediately after the record with the given `id`. - Return `null` if the given `id` does not exist or if it belongs to the last record. 2. `get_previous_id(id: string) -> string | null` - Return the `id` of the record immediately before the record with the given `id`. - Return `null` if the given `id` does not exist or if it belongs to the first record. Your implementation should preserve the original order of the input records and should be efficient for repeated lookups. State the time and space complexity of your approach.

Quick Answer: This question evaluates understanding of ordered data traversal and efficient lookup design, assessing competency with data structures, indexing and reasoning about time and space complexity for repeated neighbor queries.

You are given an ordered list of records. Each record is a dictionary-like object that contains a unique string field called "id" and may contain any number of additional attributes. You are also given a list of lookup operations. Each operation is a pair `(op, record_id)` where `op` is either `"next"` or `"prev"`. For each operation: - `"next"`: return the `id` of the record immediately after `record_id` - `"prev"`: return the `id` of the record immediately before `record_id` Return the answers for all operations in order. If the given `id` does not exist, or if it has no neighbor in the requested direction, return `None` for that operation. Your solution should preserve the original order of the records and be efficient for repeated lookups.

Constraints

  • 0 <= len(records) <= 200000
  • 0 <= len(operations) <= 200000
  • Each record contains a unique string key `"id"`
  • Each operation is either `("next", id)` or `("prev", id)`

Examples

Input: ([{"id": "u1", "name": "Ann"}, {"id": "u2", "age": 30}, {"id": "u3", "active": True}], [("next", "u1"), ("prev", "u3"), ("next", "u3"), ("prev", "u1"), ("next", "missing")])

Expected Output: ["u2", "u2", None, None, None]

Explanation: The ordered ids are ["u1", "u2", "u3"]. So the next id after "u1" is "u2", the previous id before "u3" is "u2", and the boundary or missing-id lookups return None.

Input: ([], [("next", "x"), ("prev", "x")])

Expected Output: [None, None]

Explanation: There are no records, so every lookup returns None.

Input: ([{"id": "only", "value": 10}], [("next", "only"), ("prev", "only"), ("prev", "missing")])

Expected Output: [None, None, None]

Explanation: A single record has neither a previous nor a next neighbor, and a missing id also returns None.

Input: ([{"id": "alpha"}, {"id": "beta", "score": 7}, {"id": "gamma"}, {"id": "delta", "flag": False}], [("prev", "gamma"), ("next", "beta"), ("prev", "alpha"), ("next", "delta")])

Expected Output: ["beta", "gamma", None, None]

Explanation: The list order is preserved as ["alpha", "beta", "gamma", "delta"]. So gamma's previous is beta, beta's next is gamma, alpha has no previous, and delta has no next.

Input: ([{"id": "id-10", "x": 1}, {"id": "id-2", "x": 2}, {"id": "id-30", "x": 3}], [("next", "id-10"), ("next", "id-2"), ("prev", "id-30")])

Expected Output: ["id-2", "id-30", "id-2"]

Explanation: Neighboring records depend on input order, not lexicographic order of the ids.

Hints

  1. If you scan the list for every lookup, repeated queries become too slow. Preprocess the records once.
  2. Store each record's position by `id` in a hash map. Then the neighboring record is just at index `i - 1` or `i + 1` if that index is in bounds.
Last updated: May 19, 2026

Related Coding Questions

  • Implement an in-memory storage with TTL and scans - Ziprecruiter (medium)
  • Design a voting counter for restaurants - Ziprecruiter (medium)

Loading coding console...

PracHub

Master your tech interviews with 8,500+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities
  • Student Access

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.