Bird
Raised Fist0
Interview Prepbinary-search-treesmediumAmazonFacebookMicrosoftGoogle

Lowest Common Ancestor of a BST

Choose your preparation mode4 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
🎯
Lowest Common Ancestor of a BST
mediumTREEAmazonFacebookMicrosoft

Imagine you are navigating a family tree of employees in a company organized by hierarchy, and you want to find the closest common manager of two employees quickly.

💡 This problem asks you to find the lowest common ancestor (LCA) of two nodes in a BST. Beginners often struggle because they confuse BST properties with general binary trees and don't leverage the BST ordering to optimize the search.
📋
Problem Statement

Given a binary search tree (BST) and two nodes p and q in the BST, find the lowest common ancestor (LCA) of p and q. The LCA is defined as the lowest node in the BST that has both p and q as descendants (where we allow a node to be a descendant of itself). Input: root of BST, nodes p and q. Output: the LCA node.

The number of nodes in the tree is in the range [1, 10^5]All node values are uniquep and q are different nodes and both exist in the BST
💡
Example
Input"root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8"
Output6

The LCA of nodes 2 and 8 is 6 because 6 is the lowest node that has both 2 and 8 as descendants.

Input"root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4"
Output2

The LCA of nodes 2 and 4 is 2 because a node can be a descendant of itself.

  • p is ancestor of q → LCA is p
  • q is ancestor of p → LCA is q
  • p and q are on different subtrees → LCA is root or intermediate node
  • Tree with only one node → LCA is that node
⚠️
Common Mistakes
Not leveraging BST properties and treating tree as general binary tree

Solution becomes inefficient and may time out on large inputs

Use BST ordering to prune search space

Assuming LCA must be strictly ancestor, ignoring that node can be ancestor of itself

Incorrect LCA returned when one node is ancestor of the other

Allow returning p or q if it matches current node during search

Not handling null root or empty tree cases

Code may crash or return incorrect results

Add base case checks for null root

Using recursion without considering stack overflow for deep trees

Stack overflow error on very deep BSTs

Use iterative approach to avoid recursion stack

Comparing node values incorrectly (e.g., using == instead of < or >)

Incorrect traversal direction, wrong LCA found

Use proper comparison operators to decide subtree traversal

🧠
Brute Force (Find Paths and Compare)
💡 This approach exists to build intuition by explicitly finding paths to both nodes and then comparing them. It is straightforward but inefficient, helping beginners understand the problem structure.

Intuition

Find the path from root to p and root to q separately, then compare these paths to find the last common node, which is the LCA.

Algorithm

  1. Traverse the BST from root to find the path to node p and store it.
  2. Traverse the BST from root to find the path to node q and store it.
  3. Compare the two paths node by node until they differ.
  4. Return the last common node found in both paths as the LCA.
💡 This algorithm is easy to visualize but requires extra space and repeated traversals, which can be inefficient for large trees.
</>
Code
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def find_path(root, target, path):
    if not root:
        return False
    path.append(root)
    if root.val == target.val:
        return True
    if (root.left and find_path(root.left, target, path)) or (root.right and find_path(root.right, target, path)):
        return True
    path.pop()
    return False

def lowestCommonAncestor(root, p, q):
    path_p = []
    path_q = []
    find_path(root, p, path_p)
    find_path(root, q, path_q)
    i = 0
    while i < len(path_p) and i < len(path_q) and path_p[i] == path_q[i]:
        i += 1
    return path_p[i-1]

# Example usage:
# Construct BST nodes
# root = TreeNode(6)
# ... build tree ...
# print(lowestCommonAncestor(root, p, q).val)
Line Notes
def find_path(root, target, path):Defines helper to find path from root to target node
if not root:Base case: reached leaf without finding target
path.append(root)Add current node to path as we go down
if root.val == target.val:Check if current node is target
if (root.left and find_path(root.left, target, path)) or (root.right and find_path(root.right, target, path))Recursively search left or right subtree
path.pop()Backtrack if target not found in this path
find_path(root, p, path_p)Find path to node p
find_path(root, q, path_q)Find path to node q
while i < len(path_p) and i < len(path_q) and path_p[i] == path_q[i]:Compare paths to find last common node
return path_p[i-1]Return the last common ancestor node
import java.util.*;
class TreeNode {
    int val;
    TreeNode left, right;
    TreeNode(int x) { val = x; }
}
public class Solution {
    public boolean findPath(TreeNode root, TreeNode target, List<TreeNode> path) {
        if (root == null) return false;
        path.add(root);
        if (root.val == target.val) return true;
        if ((root.left != null && findPath(root.left, target, path)) || (root.right != null && findPath(root.right, target, path)))
            return true;
        path.remove(path.size() - 1);
        return false;
    }
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        List<TreeNode> pathP = new ArrayList<>();
        List<TreeNode> pathQ = new ArrayList<>();
        findPath(root, p, pathP);
        findPath(root, q, pathQ);
        int i = 0;
        while (i < pathP.size() && i < pathQ.size() && pathP.get(i) == pathQ.get(i)) {
            i++;
        }
        return pathP.get(i - 1);
    }
    // main method and tree construction can be added for testing
}
Line Notes
public boolean findPath(TreeNode root, TreeNode target, List<TreeNode> path)Helper to find path from root to target
if (root == null) return false;Base case: no node found
path.add(root);Add current node to path
if (root.val == target.val) return true;Check if current node is target
if ((root.left != null && findPath(root.left, target, path)) || (root.right != null && findPath(root.right, target, path)))Search left or right subtree recursively
path.remove(path.size() - 1);Backtrack if target not found
findPath(root, p, pathP);Find path to p
findPath(root, q, pathQ);Find path to q
while (i < pathP.size() && i < pathQ.size() && pathP.get(i) == pathQ.get(i))Compare paths to find last common node
return pathP.get(i - 1);Return LCA node
#include <iostream>
#include <vector>
using namespace std;
struct TreeNode {
    int val;
    TreeNode *left, *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
bool findPath(TreeNode* root, TreeNode* target, vector<TreeNode*>& path) {
    if (!root) return false;
    path.push_back(root);
    if (root->val == target->val) return true;
    if ((root->left && findPath(root->left, target, path)) || (root->right && findPath(root->right, target, path)))
        return true;
    path.pop_back();
    return false;
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    vector<TreeNode*> pathP, pathQ;
    findPath(root, p, pathP);
    findPath(root, q, pathQ);
    int i = 0;
    while (i < pathP.size() && i < pathQ.size() && pathP[i] == pathQ[i])
        i++;
    return pathP[i - 1];
}
// main function and tree construction can be added for testing
Line Notes
bool findPath(TreeNode* root, TreeNode* target, vector<TreeNode*>& path)Helper to find path from root to target node
if (!root) return false;Base case: reached null node
path.push_back(root);Add current node to path
if (root->val == target->val) return true;Check if current node is target
if ((root->left && findPath(root->left, target, path)) || (root->right && findPath(root->right, target, path)))Recursively search left or right subtree
path.pop_back();Backtrack if target not found
findPath(root, p, pathP);Find path to p
findPath(root, q, pathQ);Find path to q
while (i < pathP.size() && i < pathQ.size() && pathP[i] == pathQ[i])Compare paths to find last common node
return pathP[i - 1];Return LCA node
function TreeNode(val, left=null, right=null) {
    this.val = val;
    this.left = left;
    this.right = right;
}
function findPath(root, target, path) {
    if (!root) return false;
    path.push(root);
    if (root.val === target.val) return true;
    if ((root.left && findPath(root.left, target, path)) || (root.right && findPath(root.right, target, path)))
        return true;
    path.pop();
    return false;
}
function lowestCommonAncestor(root, p, q) {
    const pathP = [];
    const pathQ = [];
    findPath(root, p, pathP);
    findPath(root, q, pathQ);
    let i = 0;
    while (i < pathP.length && i < pathQ.length && pathP[i] === pathQ[i]) {
        i++;
    }
    return pathP[i - 1];
}
// Example usage:
// let root = new TreeNode(6);
// ... build tree ...
// console.log(lowestCommonAncestor(root, p, q).val);
Line Notes
function findPath(root, target, path)Helper to find path from root to target
if (!root) return false;Base case: no node found
path.push(root);Add current node to path
if (root.val === target.val) return true;Check if current node is target
if ((root.left && findPath(root.left, target, path)) || (root.right && findPath(root.right, target, path)))Recursively search left or right subtree
path.pop();Backtrack if target not found
findPath(root, p, pathP);Find path to p
findPath(root, q, pathQ);Find path to q
while (i < pathP.length && i < pathQ.length && pathP[i] === pathQ[i])Compare paths to find last common node
return pathP[i - 1];Return LCA node
Complexity
TimeO(n) in worst case, where n is number of nodes, because we may traverse the tree twice to find paths
SpaceO(n) for storing paths and recursion stack

Finding each path can take O(n) time in worst case, and storing paths requires O(n) space. Comparing paths is O(n) as well.

💡 For n=20 nodes, this means up to 40 node visits plus storing paths, which is inefficient for large trees.
Interview Verdict: Accepted but inefficient; useful for understanding

This approach is easy to implement but not optimal. It helps beginners understand the problem before moving to better solutions.

🧠
Better (Recursive BST Property Exploitation)
💡 This approach leverages BST properties to avoid searching entire paths, improving efficiency by pruning unnecessary branches.

Intuition

Because BST nodes are ordered, if both p and q are smaller than current node, LCA lies in left subtree; if both are greater, LCA lies in right subtree; otherwise current node is LCA.

Algorithm

  1. Start at root node.
  2. If both p and q values are less than root's value, recurse into left subtree.
  3. If both p and q values are greater than root's value, recurse into right subtree.
  4. Otherwise, root is the LCA.
💡 This algorithm is more efficient because it uses BST ordering to avoid unnecessary subtree searches.
Recurrence:LCA(root) = if p.val < root.val and q.val < root.val then LCA(root.left) else if p.val > root.val and q.val > root.val then LCA(root.right) else root
</>
Code
def lowestCommonAncestor(root, p, q):
    if root is None:
        return None
    if p.val < root.val and q.val < root.val:
        return lowestCommonAncestor(root.left, p, q)
    elif p.val > root.val and q.val > root.val:
        return lowestCommonAncestor(root.right, p, q)
    else:
        return root

# Example usage:
# print(lowestCommonAncestor(root, p, q).val)
Line Notes
if root is None:Base case: empty subtree
if p.val < root.val and q.val < root.val:Both nodes smaller, go left
return lowestCommonAncestor(root.left, p, q)Recurse left subtree
elif p.val > root.val and q.val > root.val:Both nodes greater, go right
return lowestCommonAncestor(root.right, p, q)Recurse right subtree
else:Nodes split, current root is LCA
return rootReturn LCA node
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    if (root == null) return null;
    if (p.val < root.val && q.val < root.val) {
        return lowestCommonAncestor(root.left, p, q);
    } else if (p.val > root.val && q.val > root.val) {
        return lowestCommonAncestor(root.right, p, q);
    } else {
        return root;
    }
}
// main method and tree construction can be added for testing
Line Notes
if (root == null) return null;Base case: empty subtree
if (p.val < root.val && q.val < root.val)Both nodes smaller, go left
return lowestCommonAncestor(root.left, p, q);Recurse left subtree
else if (p.val > root.val && q.val > root.val)Both nodes greater, go right
return lowestCommonAncestor(root.right, p, q);Recurse right subtree
elseNodes split, current root is LCA
return root;Return LCA node
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    if (!root) return nullptr;
    if (p->val < root->val && q->val < root->val) {
        return lowestCommonAncestor(root->left, p, q);
    } else if (p->val > root->val && q->val > root->val) {
        return lowestCommonAncestor(root->right, p, q);
    } else {
        return root;
    }
}
// main function and tree construction can be added for testing
Line Notes
if (!root) return nullptr;Base case: empty subtree
if (p->val < root->val && q->val < root->val)Both nodes smaller, go left
return lowestCommonAncestor(root->left, p, q);Recurse left subtree
else if (p->val > root->val && q->val > root->val)Both nodes greater, go right
return lowestCommonAncestor(root->right, p, q);Recurse right subtree
elseNodes split, current root is LCA
return root;Return LCA node
function lowestCommonAncestor(root, p, q) {
    if (!root) return null;
    if (p.val < root.val && q.val < root.val) {
        return lowestCommonAncestor(root.left, p, q);
    } else if (p.val > root.val && q.val > root.val) {
        return lowestCommonAncestor(root.right, p, q);
    } else {
        return root;
    }
}
// Example usage:
// console.log(lowestCommonAncestor(root, p, q).val);
Line Notes
if (!root) return null;Base case: empty subtree
if (p.val < root.val && q.val < root.val)Both nodes smaller, go left
return lowestCommonAncestor(root.left, p, q);Recurse left subtree
else if (p.val > root.val && q.val > root.val)Both nodes greater, go right
return lowestCommonAncestor(root.right, p, q);Recurse right subtree
elseNodes split, current root is LCA
return root;Return LCA node
Complexity
TimeO(h), where h is the height of the BST
SpaceO(h) due to recursion stack

Each recursive call moves down one level of the tree, so time and space depend on tree height, which is O(log n) for balanced BSTs and O(n) worst case.

💡 For a balanced BST with 20 nodes, this means about 5 steps, much faster than brute force.
Interview Verdict: Accepted and efficient for balanced BSTs

This approach is optimal for BSTs and is the standard solution interviewers expect.

🧠
Optimal (Iterative BST Property Exploitation)
💡 This approach optimizes the recursive solution by using iteration to avoid recursion overhead and stack usage.

Intuition

Use a loop to traverse the BST from root, moving left or right based on p and q values until the split point (LCA) is found.

Algorithm

  1. Initialize current node as root.
  2. While current node is not null:
  3. If both p and q values are less than current node's value, move to left child.
  4. Else if both p and q values are greater than current node's value, move to right child.
  5. Else current node is LCA; break and return it.
💡 This iterative approach is straightforward and efficient, avoiding recursion stack overhead.
</>
Code
def lowestCommonAncestor(root, p, q):
    current = root
    while current:
        if p.val < current.val and q.val < current.val:
            current = current.left
        elif p.val > current.val and q.val > current.val:
            current = current.right
        else:
            return current

# Example usage:
# print(lowestCommonAncestor(root, p, q).val)
Line Notes
current = rootStart traversal from root
while current:Loop until LCA found or tree ends
if p.val < current.val and q.val < current.val:Both nodes smaller, go left
current = current.leftMove to left child
elif p.val > current.val and q.val > current.val:Both nodes greater, go right
current = current.rightMove to right child
else:Nodes split, current is LCA
return currentReturn LCA node
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    TreeNode current = root;
    while (current != null) {
        if (p.val < current.val && q.val < current.val) {
            current = current.left;
        } else if (p.val > current.val && q.val > current.val) {
            current = current.right;
        } else {
            return current;
        }
    }
    return null;
}
// main method and tree construction can be added for testing
Line Notes
TreeNode current = root;Initialize traversal pointer
while (current != null)Loop until LCA found or end
if (p.val < current.val && q.val < current.val)Both nodes smaller, go left
current = current.left;Move left
else if (p.val > current.val && q.val > current.val)Both nodes greater, go right
current = current.right;Move right
elseNodes split, current is LCA
return current;Return LCA node
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    TreeNode* current = root;
    while (current) {
        if (p->val < current->val && q->val < current->val) {
            current = current->left;
        } else if (p->val > current->val && q->val > current->val) {
            current = current->right;
        } else {
            return current;
        }
    }
    return nullptr;
}
// main function and tree construction can be added for testing
Line Notes
TreeNode* current = root;Initialize traversal pointer
while (current)Loop until LCA found or end
if (p->val < current->val && q->val < current->val)Both nodes smaller, go left
current = current->left;Move left
else if (p->val > current->val && q->val > current->val)Both nodes greater, go right
current = current->right;Move right
elseNodes split, current is LCA
return current;Return LCA node
function lowestCommonAncestor(root, p, q) {
    let current = root;
    while (current) {
        if (p.val < current.val && q.val < current.val) {
            current = current.left;
        } else if (p.val > current.val && q.val > current.val) {
            current = current.right;
        } else {
            return current;
        }
    }
    return null;
}
// Example usage:
// console.log(lowestCommonAncestor(root, p, q).val);
Line Notes
let current = root;Initialize traversal pointer
while (current)Loop until LCA found or end
if (p.val < current.val && q.val < current.val)Both nodes smaller, go left
current = current.left;Move left
else if (p.val > current.val && q.val > current.val)Both nodes greater, go right
current = current.right;Move right
elseNodes split, current is LCA
return current;Return LCA node
Complexity
TimeO(h), where h is the height of the BST
SpaceO(1) additional space

Iterative traversal visits nodes down the tree height only, no recursion stack used.

💡 For balanced BST with 20 nodes, this means about 5 steps and constant extra space.
Interview Verdict: Accepted and optimal for interviews

This is the best approach to code in interviews for this problem due to its efficiency and simplicity.

📊
All Approaches - One-Glance Tradeoffs
💡 In interviews, coding the iterative BST property approach is best for efficiency and clarity. Brute force is good for initial explanation but not for coding.
ApproachTimeSpaceStack RiskReconstructUse In Interview
1. Brute Force (Find Paths and Compare)O(n)O(n)Yes (due to recursion in path finding)Yes (paths explicitly stored)Mention only - never code
2. Recursive BST Property ExploitationO(h)O(h)Yes (deep recursion possible)N/AGood to explain and code if comfortable with recursion
3. Iterative BST Property ExploitationO(h)O(1)NoN/ABest approach to code in interviews
💼
Interview Strategy
💡 Use this guide to understand the problem deeply before interviews. Start with brute force to build intuition, then move to optimized BST property solutions. Practice coding and explaining each step clearly.

How to Present

Step 1: Clarify the problem and confirm BST properties and input guarantees.Step 2: Describe the brute force approach of finding paths and comparing them.Step 3: Explain how BST ordering allows pruning and leads to a recursive solution.Step 4: Present the iterative solution as the optimal approach.Step 5: Code the iterative solution and test with examples.

Time Allocation

Clarify: 2min → Approach: 3min → Code: 8min → Test: 2min. Total ~15min

What the Interviewer Tests

Interviewer tests your understanding of BST properties, ability to optimize from brute force, and clean coding skills. They also check if you handle edge cases and explain your approach clearly.

Common Follow-ups

  • What if the tree is not a BST? → Use general binary tree LCA algorithm.
  • Can you find LCA without parent pointers? → Yes, using recursion or iteration as shown.
💡 These follow-ups test your adaptability and understanding of related problems.
🔍
Pattern Recognition

When to Use

1) Input is a BST, 2) Need to find common ancestor of two nodes, 3) Nodes guaranteed to exist, 4) Want efficient search using BST ordering

Signature Phrases

'lowest common ancestor''binary search tree''both nodes are descendants''node can be descendant of itself'

NOT This Pattern When

General binary tree LCA problems without BST ordering

Similar Problems

Lowest Common Ancestor of a Binary Tree - similar but no BST propertyValidate Binary Search Tree - uses BST ordering logicFind Distance Between Nodes in BST - uses LCA to compute distance

Practice

(1/5)
1. Given the following code snippet for converting a sorted array to a height-balanced BST, what is the value of the root node's value after the first call to helper with input nums = [1, 3, 5]?
easy
A. 3
B. 1
C. 5
D. None

Solution

  1. Step 1: Calculate mid index for initial call

    For nums=[1,3,5], left=0, right=2, mid=(0+2)//2=1.
  2. Step 2: Identify root value

    nums[mid] = nums[1] = 3, so root node value is 3.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Mid index calculation picks 3 as root [OK]
Hint: Mid index picks middle element as root [OK]
Common Mistakes:
  • Choosing first or last element as root
  • Off-by-one mid calculation
2. Consider the following code for computing the range sum of a BST. Given the BST with root value 10, left child 5, right child 15, and range [7, 15], what is the final value of total returned by rangeSumBST?
easy
A. 25
B. 15
C. 40
D. 30

Solution

  1. Step 1: Trace initial stack and total

    Start with stack=[10], total=0.
  2. Step 2: Pop 10 (in range), add 10, push left(5) and right(15)

    total=10, stack=[5,15]
  3. Step 3: Pop 15 (in range), add 15, push left(null) and right(null)

    total=25, stack=[5,null,null]
  4. Step 4: Pop null (skip), then pop null (skip), then pop 5 (less than low=7), push right(null)

    total=25, stack=[null]
  5. Step 5: Pop null (skip), stack empty, return total=25

    5 is less than low, so it is skipped and not added.
  6. Final Answer:

    Option A -> Option A
  7. Quick Check:

    Sum includes 10 and 15 only, total=25 [OK]
Hint: Only nodes within [7,15] add to total [OK]
Common Mistakes:
  • Adding nodes outside range
  • Forgetting to push children after adding node
3. The following code attempts to implement a BST Iterator using the Morris traversal technique. Identify the bug that can cause the tree structure to remain corrupted after iteration.
class BSTIterator:
    def __init__(self, root):
        self.current = root
        self.next_val = None
        self._advance()

    def _advance(self):
        while self.current:
            if not self.current.left:
                self.next_val = self.current.val
                self.current = self.current.right
                return
            else:
                pre = self.current.left
                while pre.right and pre.right != self.current:
                    pre = pre.right
                if not pre.right:
                    pre.right = self.current
                    self.current = self.current.left
                else:
                    # BUG: Missing restoration of thread
                    self.next_val = self.current.val
                    self.current = self.current.right
medium
A. Line resetting pre.right to null is missing, so threads are not removed.
B. Line setting self.next_val = self.current.val is incorrect and should be removed.
C. Line moving self.current to self.current.left should be self.current.right instead.
D. Line initializing self.current = root in __init__ is incorrect and should be null.

Solution

  1. Step 1: Identify thread restoration step

    In Morris traversal, after visiting a node, the temporary thread (pre.right) must be reset to null to restore the tree.
  2. Step 2: Locate missing restoration

    The code omits resetting pre.right = None in the else block, causing the tree to remain modified after iteration.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Missing thread removal corrupts tree structure [OK]
Hint: Always restore threads to avoid tree corruption [OK]
Common Mistakes:
  • Forgetting to remove threads
  • Misplacing next_val assignment
  • Incorrect current pointer updates
4. What is the time complexity of the iterative inorder traversal approach to find the kth smallest element in a BST, where H is the height of the tree and k is the input parameter?
medium
A. O(H + k), where H is the height of the tree and k is the kth element to find
B. O(k), since only k nodes are visited
C. O(k log n), assuming balanced BST
D. O(n), where n is the total number of nodes in the BST

Solution

  1. Step 1: Analyze traversal steps

    The algorithm traverses down to the leftmost node (cost O(H)) and then visits k nodes in inorder sequence.
  2. Step 2: Combine costs

    Total time is O(H) to reach leftmost node plus O(k) to visit k nodes, so O(H + k).
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Traversal cost depends on height plus k nodes visited [OK]
Hint: Traversal cost includes height plus k nodes visited [OK]
Common Mistakes:
  • Assuming O(n) always
  • Ignoring height cost
  • Assuming only k nodes visited without stack overhead
5. Suppose the problem is extended so that multiple pairs of nodes (more than two nodes) are swapped in the BST, possibly non-adjacent. Which of the following modifications to the recovery algorithm is correct and efficient?
hard
A. Use the Morris inorder traversal to detect all violations and store all nodes involved, then sort their values and reassign in inorder traversal.
B. Run the Morris traversal multiple times, each time swapping the first detected violation nodes until no violations remain.
C. Use the brute force approach: inorder traversal to collect all values, sort them, then overwrite the tree nodes in inorder traversal.
D. Modify the Morris traversal to swap nodes immediately upon detecting each violation without storing nodes, fixing all swaps in one pass.

Solution

  1. Step 1: Understand the problem extension

    Multiple pairs of nodes swapped means multiple violations, possibly complex to detect and fix in one pass.
  2. Step 2: Evaluate approaches

    Morris traversal detects only two nodes swapped optimally; multiple swaps require collecting all values, sorting, and rewriting nodes, which brute force does efficiently.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Brute force approach handles multiple swaps correctly by sorting all values [OK]
Hint: Multiple swaps require full value sorting and rewriting [OK]
Common Mistakes:
  • Assuming Morris traversal can fix multiple swaps in one pass
  • Trying to swap nodes immediately without full detection
  • Running multiple passes of Morris traversal inefficiently