Fix a BST with two misplaced keys
Company: TikTok
Role: Machine Learning Engineer
Category: Coding & Algorithms
Difficulty: Medium
Interview Round: Technical Screen
Quick Answer: This interview question evaluates algorithm design, data structures, correctness, complexity, edge cases, and implementation details in a realistic interview setting. A strong answer for Fix a BST with two misplaced keys states assumptions, handles edge cases, explains trade-offs, and shows how to validate the result clearly.
Constraints
- The number of nodes is in the range [1, 10^4] for non-empty trees; the empty-tree case ([]) is also handled.
- Exactly two nodes' keys were swapped.
- Node values fit in a 32-bit signed integer and may be negative.
- The tree structure must not change — only node values may be corrected.
- Input/output use level-order arrays with null for missing children and trailing nulls trimmed.
Examples
Input: ([1, 3, None, None, 2],)
Expected Output: [3, 1, None, None, 2]
Explanation: Adjacent violation: in-order is 3,2,1 region; swapping 1 and 3 restores increasing order.
Input: ([3, 1, 4, None, None, 2],)
Expected Output: [2, 1, 4, None, None, 3]
Explanation: Non-adjacent violation: keys 2 and 3 were swapped; restoring them yields a valid BST.
Input: ([2, 3, 1],)
Expected Output: [2, 1, 3]
Explanation: Left child 3 and right child 1 violate BST order; swapping them fixes it.
Input: ([1],)
Expected Output: [1]
Explanation: Single node — trivially valid, returned unchanged.
Input: ([],)
Expected Output: []
Explanation: Empty tree edge case — returned unchanged.
Input: ([10, 5, 8, 2, 20],)
Expected Output: [10, 5, 20, 2, 8]
Explanation: Non-adjacent violation in a deeper unbalanced tree: 8 and 20 were swapped.
Hints
- An in-order traversal of a valid BST is strictly increasing. After swapping two keys, the in-order sequence has either one or two positions where a value is greater than the value that follows it.
- Walk the in-order sequence tracking the previous node. The FIRST time you see prev.val > cur.val, record `first = prev`. EVERY time it happens, record `second = cur`. Then swap first.val and second.val.
- For an adjacent violation there is exactly one descending step, so first = prev and second = cur of that single step. For a non-adjacent violation there are two descending steps; first comes from the earlier step and second from the later step.
- To hit O(1) extra space without recursion or a stack, use Morris traversal: thread each node's in-order predecessor's right pointer to the node, then undo the thread on the way back.