Bird
Raised Fist0
DSA Javaprogramming

BST Inorder Predecessor in DSA Java

Choose your learning style10 modes available
Mental Model
The inorder predecessor of a node in a BST is the node that comes just before it when we list all nodes in sorted order.
Analogy: Imagine a line of people sorted by height. The inorder predecessor of a person is the person just shorter than them standing immediately before in line.
      5
     / \
    3   7
   / \   \
  2   4   8
 ↑curr
Dry Run Walkthrough
Input: BST: 5 -> 3 -> 7 -> 2 -> 4 -> 8, find inorder predecessor of node with value 5
Goal: Find the node that comes just before 5 in sorted order, which is 4
Step 1: Start at node 5, check if left child exists
      5[↑curr]
     / \
    3   7
   / \   \
  2   4   8
Why: We look left because predecessor is the largest node smaller than current
Step 2: Move to left child 3, then go right as far as possible
      5
     / \
    3[↑curr] 7
   / \   \
  2   4   8
Why: The predecessor is the rightmost node in left subtree
Step 3: Move right from 3 to 4, which has no right child
      5
     / \
    3   7
   / \   \
  2   4[↑curr] 8
Why: 4 is the largest node smaller than 5
Result:
4 is the inorder predecessor of 5
Annotated Code
DSA Java
class Node {
    int val;
    Node left, right;
    Node(int val) { this.val = val; }
}

public class BSTInorderPredecessor {
    // Find inorder predecessor of given node in BST
    public static Node inorderPredecessor(Node root, Node target) {
        if (target.left != null) {
            // predecessor is rightmost node in left subtree
            Node curr = target.left;
            while (curr.right != null) {
                curr = curr.right; // move right to find max smaller
            }
            return curr;
        } else {
            // predecessor is ancestor where target is in right subtree
            Node predecessor = null;
            Node curr = root;
            while (curr != null) {
                if (target.val > curr.val) {
                    predecessor = curr; // potential predecessor
                    curr = curr.right; // move right to find closer
                } else if (target.val < curr.val) {
                    curr = curr.left; // move left
                } else {
                    break; // found target
                }
            }
            return predecessor;
        }
    }

    public static void main(String[] args) {
        Node root = new Node(5);
        root.left = new Node(3);
        root.right = new Node(7);
        root.left.left = new Node(2);
        root.left.right = new Node(4);
        root.right.right = new Node(8);

        Node target = root; // node with value 5
        Node pred = inorderPredecessor(root, target);
        if (pred != null) {
            System.out.println(pred.val);
        } else {
            System.out.println("No predecessor");
        }
    }
}
if (target.left != null) {
Check if left subtree exists to find predecessor there
Node curr = target.left;
Start at left child to find rightmost node
while (curr.right != null) {
Traverse right to find max smaller node
curr = curr.right;
Advance curr to right child
return curr;
Return rightmost node in left subtree as predecessor
Node predecessor = null;
Initialize predecessor for ancestor search
while (curr != null) {
Traverse from root to target to find predecessor ancestor
if (target.val > curr.val) {
If target is greater, curr could be predecessor
predecessor = curr;
Update predecessor candidate
curr = curr.right;
Move right to find closer predecessor
else if (target.val < curr.val) {
If target smaller, move left
curr = curr.left;
Advance curr to left child
else { break; }
Found target node, stop
return predecessor;
Return found predecessor ancestor or null
OutputSuccess
4
Complexity Analysis
Time: O(h) because we traverse down the tree height h once to find predecessor
Space: O(1) because we use only a few pointers, no extra data structures
vs Alternative: Compared to inorder traversal of entire tree O(n), this method is faster by focusing only on path to target and its left subtree
Edge Cases
Target node has no left subtree and is the smallest node
No predecessor found, returns null
DSA Java
return predecessor;
Target node has left subtree
Predecessor is rightmost node in left subtree
DSA Java
while (curr.right != null) {
Target node has no left child but has a predecessor ancestor
Ancestor with smaller value returned as predecessor
DSA Java
if (target.val > curr.val) {
When to Use This Pattern
When asked for the previous node in sorted order in a BST, use the inorder predecessor pattern to find the largest smaller node efficiently.
Common Mistakes
Mistake: Trying to find predecessor by full inorder traversal instead of targeted search
Fix: Use left subtree's rightmost node or ancestor search to find predecessor in O(h) time
Summary
Finds the node just smaller than the given node in BST sorted order.
Use when you need the previous element in sorted order without full traversal.
The predecessor is either the rightmost node in left subtree or the closest ancestor smaller than the node.

Practice

(1/5)
1. What is the inorder predecessor of a node in a Binary Search Tree (BST)?
easy
A. The node with the largest value smaller than the given node
B. The node with the smallest value larger than the given node
C. The left child of the given node
D. The right child of the given node

Solution

  1. Step 1: Understand inorder traversal order

    Inorder traversal visits nodes in ascending order for BST, so predecessor is the previous node in this order.
  2. Step 2: Define inorder predecessor

    The inorder predecessor is the node with the largest value smaller than the current node's value.
  3. Final Answer:

    The node with the largest value smaller than the given node -> Option A
  4. Quick Check:

    Inorder predecessor = largest smaller value [OK]
Hint: Predecessor is just before current node in sorted order [OK]
Common Mistakes:
  • Confusing predecessor with successor
  • Thinking predecessor is always left child
  • Assuming predecessor is the parent node
2. Which of the following Java method signatures correctly represents a function to find the inorder predecessor in a BST node?
easy
A. public Node findInorderSuccessor(Node root, int key)
B. public int findInorderPredecessor(int[] arr, int key)
C. public Node findInorderPredecessor(Node root, int key)
D. public void findInorderPredecessor(Node root)

Solution

  1. Step 1: Identify correct parameters for BST predecessor method

    We need the BST root and the key node value to find predecessor, so method should accept Node root and int key.
  2. Step 2: Check method return type and name

    Return type should be Node (the predecessor node), and method name should indicate predecessor, so 'findInorderPredecessor(Node root, int key)' fits.
  3. Final Answer:

    public Node findInorderPredecessor(Node root, int key) -> Option C
  4. Quick Check:

    Correct signature includes root, key, returns Node [OK]
Hint: Method needs root and key, returns Node predecessor [OK]
Common Mistakes:
  • Using array instead of BST Node
  • Confusing predecessor with successor method name
  • Wrong return type like void or int
3. Given the BST below and the code snippet, what will be the output?
    20
   /  \
 10   30
   
Node predecessor = findInorderPredecessor(root, 20);
System.out.println(predecessor != null ? predecessor.data : "null");
Assuming findInorderPredecessor is correctly implemented.
medium
A. null
B. 10
C. 30
D. 20

Solution

  1. Step 1: Identify inorder predecessor of node 20 in BST

    Inorder predecessor is the largest node smaller than 20. Left subtree of 20 has node 10, which is smaller and largest in left subtree.
  2. Step 2: Confirm output of print statement

    Predecessor node data is 10, so printed output is "10".
  3. Final Answer:

    10 -> Option B
  4. Quick Check:

    Largest smaller node than 20 is 10 [OK]
Hint: Predecessor is max in left subtree if left exists [OK]
Common Mistakes:
  • Printing null when left subtree exists
  • Confusing successor with predecessor
  • Printing the node itself instead of predecessor
4. Consider this buggy Java method to find the inorder predecessor in a BST:
public Node findInorderPredecessor(Node root, int key) {
    Node predecessor = null;
    while (root != null) {
        if (key < root.data) {
            root = root.left;
        } else {
            predecessor = root;
            root = root.right;
        }
    }
    return predecessor;
}
What is the main issue with this code?
medium
A. It does not handle the case when the node has a left subtree
B. It incorrectly updates predecessor when key equals root.data
C. It causes infinite loop for some inputs
D. It returns the successor instead of predecessor

Solution

  1. Step 1: Analyze traversal logic for predecessor

    The code moves left if key < root.data, else moves right and updates predecessor. But it never checks left subtree of the node itself.
  2. Step 2: Identify missing left subtree handling

    If the node has a left subtree, the predecessor is the maximum node in that left subtree, which this code does not check.
  3. Final Answer:

    It does not handle the case when the node has a left subtree -> Option A
  4. Quick Check:

    Missing left subtree max check causes wrong predecessor [OK]
Hint: Check left subtree max for predecessor if it exists [OK]
Common Mistakes:
  • Ignoring left subtree max node
  • Confusing predecessor with successor logic
  • Assuming predecessor is always ancestor
5. You have a BST and want to find the inorder predecessor of a node with value 15. The node has no left child. Which approach correctly finds the predecessor?
hard
A. Find the maximum node in the left subtree of 15
B. Return the right child of node 15
C. Return null because no left child exists
D. Traverse from root, keep track of last node with value less than 15

Solution

  1. Step 1: Understand predecessor when no left child

    If node has no left child, predecessor is one of its ancestors with value less than node's value.
  2. Step 2: Use traversal from root to track predecessor

    Traverse from root to node 15, keep updating predecessor to last node with value less than 15.
  3. Final Answer:

    Traverse from root, keep track of last node with value less than 15 -> Option D
  4. Quick Check:

    No left child means ancestor with smaller value is predecessor [OK]
Hint: Track last smaller ancestor when no left child [OK]
Common Mistakes:
  • Returning null immediately if no left child
  • Trying to find max in non-existent left subtree
  • Returning right child mistakenly
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard