PracHub
QuestionsLearningGuidesInterview Prep

Quick Overview

This question evaluates understanding of transactional state management, nested transactions, visibility semantics for set/delete operations, and efficient in-memory data-structure manipulation.

  • medium
  • xAI
  • Coding & Algorithms
  • Software Engineer

Versioned Key-Value Store with Nested Transactions (Begin, Commit, Rollback)

Company: xAI

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Onsite

Implement an in-memory versioned key-value database that supports transactional writes with three transaction-control operations: `begin` (start a transaction), `commit`, and `rollback`. Transactions may be **nested**: a `begin` issued while another transaction is open starts a new inner transaction layered on top of it. Implement the class `VersionedKVStore`: - `VersionedKVStore()` — initializes an empty store with no open transactions. - `void set(String key, int value)` — sets `key` to `value` in the current context: the innermost open transaction if one exists, otherwise the permanent store. - `int get(String key)` — returns the value of `key` as currently visible: the innermost open transaction is consulted first, then each enclosing transaction from inner to outer, then the permanent store. Returns `-1` if the key is absent, or if the most recent visible operation on it is a deletion. - `void delete(String key)` — deletes `key` in the current context. Inside a transaction, the deletion shadows any value from outer transactions or the permanent store (so `get` returns `-1`), but takes permanent effect only if committed. Deleting a key that is not visible is a no-op in effect (subsequent `get` still returns `-1`). - `void begin()` — opens a new transaction, nested inside the current innermost transaction if one is open. - `boolean commit()` — if no transaction is open, returns `false`. Otherwise merges all changes (sets and deletions) of the **innermost** open transaction into its parent transaction — or into the permanent store if it is the outermost — closes that transaction, and returns `true`. - `boolean rollback()` — if no transaction is open, returns `false`. Otherwise discards all changes made in the **innermost** open transaction, closes it, and returns `true`. Reads and writes issued outside any transaction apply directly and permanently to the store. ### Example ``` Input: ["VersionedKVStore", "set", "get", "begin", "set", "get", "begin", "delete", "get", "rollback", "get", "commit", "get", "rollback", "get"] [[], ["a", 1], ["a"], [], ["a", 2], ["a"], [], ["a"], ["a"], [], ["a"], [], ["a"], [], ["a"]] Output: [null, null, 1, null, null, 2, null, null, -1, true, 2, true, 2, false, 2] ``` Explanation: 1. `set("a", 1)` — no transaction open, written permanently. `get("a")` returns `1`. 2. `begin()` opens transaction T1; `set("a", 2)` inside T1; `get("a")` returns `2`. 3. `begin()` opens nested transaction T2; `delete("a")` inside T2; `get("a")` returns `-1` (the deletion in T2 shadows the outer value). 4. `rollback()` discards T2 and returns `true`; `get("a")` returns `2` again (T1's write is intact). 5. `commit()` merges T1 into the permanent store and returns `true`; `get("a")` returns `2`. 6. `rollback()` returns `false` — no transaction is open; `get("a")` still returns `2`. ### Constraints - At most `10^5` operations in total. - Keys are non-empty lowercase strings of length at most `20`. - `0 <= value <= 10^9` - Transaction nesting depth will not exceed `10^3`. ### Performance requirement `set` and `delete` should run in `O(1)` average time. `get` may be `O(d)` in the worst case, where `d` is the current nesting depth (an `O(1)`-average `get` is possible with a more advanced design and is a nice discussion point). `commit` and `rollback` should cost time proportional to the number of keys modified in the innermost transaction — not the size of the whole store.

Quick Answer: This question evaluates understanding of transactional state management, nested transactions, visibility semantics for set/delete operations, and efficient in-memory data-structure manipulation.

Implement an in-memory versioned key-value database that supports transactional writes with three transaction-control operations: `begin`, `commit`, and `rollback`. Transactions may be **nested**: a `begin` issued while another transaction is open starts a new inner transaction layered on top of it. Because the coding console runs a single function, drive the class through a command list. `solution(operations, args)` receives a list of method names and an aligned list of argument lists, replays them against one `VersionedKVStore` instance, and returns a list of results (one per operation). Implement `VersionedKVStore`: - `VersionedKVStore()` — empty store, no open transactions. (Result: `None`.) - `set(key, value)` — set `key` in the current context: the innermost open transaction if one exists, otherwise the permanent store. (Result: `None`.) - `get(key)` — return the value of `key` as currently visible: innermost transaction first, then each enclosing transaction inner-to-outer, then the permanent store. Return `-1` if the key is absent or if the most recent visible operation on it is a deletion. - `delete(key)` — delete `key` in the current context. Inside a transaction the deletion shadows any outer/permanent value (so `get` returns `-1`) but only takes permanent effect if committed. (Result: `None`.) - `begin()` — open a new transaction, nested inside the current innermost one if any. (Result: `None`.) - `commit()` — if no transaction is open, return `False`. Otherwise merge the innermost transaction's changes (sets and deletions) into its parent transaction — or into the permanent store if it is the outermost — close it, and return `True`. - `rollback()` — if no transaction is open, return `False`. Otherwise discard the innermost transaction's changes, close it, and return `True`. Reads and writes issued outside any transaction apply directly and permanently. ### Example ``` operations = ["VersionedKVStore", "set", "get", "begin", "set", "get", "begin", "delete", "get", "rollback", "get", "commit", "get", "rollback", "get"] args = [[], ["a", 1], ["a"], [], ["a", 2], ["a"], [], ["a"], ["a"], [], ["a"], [], ["a"], [], ["a"]] returns [None, None, 1, None, None, 2, None, None, -1, True, 2, True, 2, False, 2] ``` set a=1 permanently (get->1). T1: set a=2 (get->2). Nested T2: delete a shadows the outer value (get->-1). rollback T2 restores T1's 2. commit T1 makes a=2 permanent. The final rollback has no open transaction, so it returns False and a stays 2.

Constraints

  • At most 10^5 operations in total.
  • Keys are non-empty lowercase strings of length at most 20.
  • 0 <= value <= 10^9.
  • Transaction nesting depth will not exceed 10^3.
  • get must return -1 when a key is absent or when its most recent visible operation is a deletion.
  • commit/rollback with no open transaction must return False (or the string "false" in the C++ template) and leave the store unchanged.

Examples

Input: (["VersionedKVStore", "set", "get", "begin", "set", "get", "begin", "delete", "get", "rollback", "get", "commit", "get", "rollback", "get"], [[], ["a", 1], ["a"], [], ["a", 2], ["a"], [], ["a"], ["a"], [], ["a"], [], ["a"], [], ["a"]])

Expected Output: [None, None, 1, None, None, 2, None, None, -1, True, 2, True, 2, False, 2]

Explanation: The problem's worked example. set a=1 permanently (get->1). T1: set a=2 (get->2). T2: delete a shadows the outer value (get->-1). rollback T2 restores T1's 2. commit T1 makes a=2 permanent. Final rollback with no open transaction returns False; a stays 2.

Input: (["VersionedKVStore", "set", "begin", "delete", "commit", "get"], [[], ["x", 5], [], ["x"], [], ["x"]])

Expected Output: [None, None, None, None, True, -1]

Explanation: A deletion made inside a transaction takes permanent effect when committed: after commit, x is truly removed from the store, so get returns -1.

Hints

  1. Model open transactions as a stack of dictionaries (layers). set/delete only ever touch the top layer; when no layer is open, they touch the permanent store directly.
  2. Represent a deletion inside a transaction as an explicit tombstone (map the key to a sentinel such as None) so it can shadow a value from an outer layer or the store. Absence of the key in a layer means 'defer to the layer below'.
  3. get walks the stack top-to-bottom, returning at the first layer that contains the key (yielding -1 if that entry is a tombstone), and falls back to the permanent store.
  4. commit pops the top layer and replays each of its entries onto the layer below (or the store if it was the outermost): a real value overwrites, a tombstone deletes. rollback just pops and discards. Both return False when the stack is empty.
Last updated: Jul 2, 2026

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

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • AI Coding 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.

Related Coding Questions

  • Flatten and unflatten nested Python structures - xAI (medium)
  • Compute dasher pay from order events - xAI (medium)
  • Compute total active time per Twitter Space - xAI (medium)
  • Design a Recoverable Iterator - xAI (medium)
  • Implement Distributed Matrix Multiplication - xAI (hard)