Print BST keys in the given range

Last Updated : 19 Jun, 2026

Given the root of a Binary Search Tree (BST) and two integers low and high, return all node values that lie in the inclusive range [low, high] in ascending order.

Examples:

Input: root = [17, 4, 18, 2, 9, N, N], l = 4, h = 17

Output: [4, 9, 17]
Explanation: The BST nodes whose values lie in the range [4, 17] are 4, 9, and 17. Hence the result is returned as [4, 9, 17].

Input: root = [16, 7, 20, 1, 10, N, N], l = 13, h = 23

Output: [16, 20]
Explanation: The nodes in the range [13, 23] are 16 and 20. Hence the result is returned as [16, 20].

Try It Yourself
redirect icon

[Naive Approach] Inorder Traversal - O(n) Time and O(n) Space

Perform inorder traversal of BST to get nodes in sorted order. Collect nodes whose values lie within [low, high] range.

  • Perform inorder traversal on BST
  • At each node, check if data is between low and high
  • If yes, add to answer array
C++
#include <iostream>
#include <vector>
using namespace std;

class Node {
public:
    int data;
    Node *left, *right;

    Node(int x) {
        data = x;
        left = right = nullptr;
    }
};

void inorder(Node* root, int low, int high, vector<int>& ans) {
    if (root == nullptr) return;

    // Visit left subtree
    inorder(root->left, low, high, ans);

    // Check current node
    if (root->data >= low && root->data <= high) {
        ans.push_back(root->data);
    }

    // Visit right subtree
    inorder(root->right, low, high, ans);
}

vector<int> nodesInRange(Node* root, int low, int high) {
    vector<int> ans;
    inorder(root, low, high, ans);
    return ans;
}

int main() {
    Node* root = new Node(22);
    root->left = new Node(12);
    root->right = new Node(30);
    root->left->left = new Node(8);
    root->left->right = new Node(20);

    int low = 10, high = 22;

    vector<int> ans = nodesInRange(root, low, high);

    for (int x : ans) {
        cout << x << " ";
    }

    return 0;
}
Java
// Naive Inorder Traversal
// Time Complexity: O(n)
// Auxiliary Space: O(h)

import java.util.*;

class Node {
    int data;
    Node left, right;

    Node(int x) {
        data = x;
        left = right = null;
    }
}

class GfG {

    static void inorder(Node root, int low, int high, ArrayList<Integer> ans) {
        if (root == null) {
            return;
        }

        // Visit left subtree
        inorder(root.left, low, high, ans);

        // Add current node if it lies in the range
        if (root.data >= low && root.data <= high) {
            ans.add(root.data);
        }

        // Visit right subtree
        inorder(root.right, low, high, ans);
    }

    static ArrayList<Integer> nodesInRange(Node root, int low, int high) {
        ArrayList<Integer> ans = new ArrayList<>();

        inorder(root, low, high, ans);

        return ans;
    }

    public static void main(String[] args) {

        Node root = new Node(22);
        root.left = new Node(12);
        root.right = new Node(30);
        root.left.left = new Node(8);
        root.left.right = new Node(20);

        int low = 10;
        int high = 22;

        ArrayList<Integer> ans = nodesInRange(root, low, high);

        for (int x : ans) {
            System.out.print(x + " ");
        }
    }
}
Python
# Python program to find nodes in a BST within a given range using inorder traversal

class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None

def inorder(root, low, high, ans):
    if root is None:
        return
    
    # Visit left subtree
    inorder(root.left, low, high, ans)
    
    # Check current node
    if low <= root.data <= high:
        ans.append(root.data)
    
    # Visit right subtree
    inorder(root.right, low, high, ans)

def nodesInRange(root, low, high):
    ans = []
    inorder(root, low, high, ans)
    return ans

# Driver code
if __name__ == "__main__":
    root = Node(22)
    root.left = Node(12)
    root.right = Node(30)
    root.left.left = Node(8)
    root.left.right = Node(20)
    
    low, high = 10, 22
    
    ans = nodesInRange(root, low, high)
    
    print(' '.join(map(str, ans)))
C#
// C# program to find nodes in a BST within a given range using inorder traversal
using System;
using System.Collections.Generic;

class Node {
    public int data;
    public Node left, right;
    
    public Node(int x) {
        data = x;
        left = null;
        right = null;
    }
}

class GfG {
    
    static void inorder(Node root, int low, int high, List<int> ans) {
        if (root == null) return;
        
        // Visit left subtree
        inorder(root.left, low, high, ans);
        
        // Check current node
        if (root.data >= low && root.data <= high) {
            ans.Add(root.data);
        }
        
        // Visit right subtree
        inorder(root.right, low, high, ans);
    }
    
    static List<int> nodesInRange(Node root, int low, int high) {
        List<int> ans = new List<int>();
        inorder(root, low, high, ans);
        return ans;
    }
    
    static void Main(string[] args) {
        Node root = new Node(22);
        root.left = new Node(12);
        root.right = new Node(30);
        root.left.left = new Node(8);
        root.left.right = new Node(20);
        
        int low = 10, high = 22;
        
        List<int> ans = nodesInRange(root, low, high);
        
        foreach (int x in ans) {
            Console.Write(x + " ");
        }
    }
}
JavaScript
// JavaScript program to find nodes in a BST within a given range using inorder traversal

class Node {
    constructor(x) {
        this.data = x;
        this.left = null;
        this.right = null;
    }
}

function inorder(root, low, high, ans) {
    if (root === null) return;
    
    // Visit left subtree
    inorder(root.left, low, high, ans);
    
    // Check current node
    if (root.data >= low && root.data <= high) {
        ans.push(root.data);
    }
    
    // Visit right subtree
    inorder(root.right, low, high, ans);
}

function nodesInRange(root, low, high) {
    let ans = [];
    inorder(root, low, high, ans);
    return ans;
}

// Driver code
const root = new Node(22);
root.left = new Node(12);
root.right = new Node(30);
root.left.left = new Node(8);
root.left.right = new Node(20);

const low = 10, high = 22;

const ans = nodesInRange(root, low, high);

console.log(ans.join(' '));

Output
12 20 22 

[Optimal Approach] Pruned Inorder Traversal - O(n) Time and O(n) Space

Use BST property to prune unnecessary subtrees. If current node value is less than low, skip left subtree. If greater than high, skip right subtree. Collect only nodes within range in sorted order.

  • If root is null, return
  • If root->data lies in range, traverse left, add root, traverse right
  • If root->data is less than low, traverse right only
  • If root->data is greater than high, traverse left only
C++
#include <iostream>
#include <vector>
using namespace std;

class Node {
public:
    int data;
    Node *left, *right;

    Node(int x) {
        data = x;
        left = right = nullptr;
    }
};

void appendNodes(Node* root, int low, int high, vector<int>& ans) {
    if (root == nullptr) return;

    // Current node lies within the required range
    if (root->data >= low && root->data <= high) {
        appendNodes(root->left, low, high, ans);
        ans.push_back(root->data);
        appendNodes(root->right, low, high, ans);
    }
    
    // Current node is smaller than the range
    else if (root->data < low) {
        appendNodes(root->right, low, high, ans);
    }
    
    // Current node is greater than the range
    else {
        appendNodes(root->left, low, high, ans);
    }
}

vector<int> nodesInRange(Node *root, int low, int high) {
    vector<int> ans;
    appendNodes(root, low, high, ans);
    return ans;
}

int main() {
    Node* root = new Node(22);
    root->left = new Node(12);
    root->right = new Node(30);
    root->left->left = new Node(8);
    root->left->right = new Node(20);

    int low = 10, high = 22;

    vector<int> ans = nodesInRange(root, low, high);

    for (int x : ans) {
        cout << x << " ";
    }

    return 0;
}
Java
import java.util.*;

class Node {
    int data;
    Node left, right;

    Node(int x) {
        data = x;
        left = right = null;
    }
}

class GfG {

    static void appendNodes(Node root, int low, int high, ArrayList<Integer> ans) {
        if (root == null) {
            return;
        }

        // Current node lies within the required range
        if (root.data >= low && root.data <= high) {
            appendNodes(root.left, low, high, ans);
            ans.add(root.data);
            appendNodes(root.right, low, high, ans);
        }
        // Current node is smaller than the range
        else if (root.data < low) {
            appendNodes(root.right, low, high, ans);
        }
        // Current node is greater than the range
        else {
            appendNodes(root.left, low, high, ans);
        }
    }

    static ArrayList<Integer> nodesInRange(Node root, int low, int high) {
        ArrayList<Integer> ans = new ArrayList<>();
        appendNodes(root, low, high, ans);
        return ans;
    }

    public static void main(String[] args) {

        Node root = new Node(22);
        root.left = new Node(12);
        root.right = new Node(30);
        root.left.left = new Node(8);
        root.left.right = new Node(20);

        int low = 10;
        int high = 22;

        ArrayList<Integer> ans = nodesInRange(root, low, high);

        for (int x : ans) {
            System.out.print(x + " ");
        }
    }
}
Python
# Python program to find nodes in a BST within a given range

class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None

def appendNodes(root, low, high, ans):
    if root is None:
        return
    
    # Current node lies within the required range
    if low <= root.data <= high:
        appendNodes(root.left, low, high, ans)
        ans.append(root.data)
        appendNodes(root.right, low, high, ans)
    # Current node is smaller than the range
    elif root.data < low:
        appendNodes(root.right, low, high, ans)
    # Current node is greater than the range
    else:
        appendNodes(root.left, low, high, ans)

def nodesInRange(root, low, high):
    ans = []
    appendNodes(root, low, high, ans)
    return ans

# Driver code
if __name__ == "__main__":
    root = Node(22)
    root.left = Node(12)
    root.right = Node(30)
    root.left.left = Node(8)
    root.left.right = Node(20)
    
    low, high = 10, 22
    
    ans = nodesInRange(root, low, high)
    
    print(' '.join(map(str, ans)))
C#
// C# program to find nodes in a BST within a given range
using System;
using System.Collections.Generic;

class Node {
    public int data;
    public Node left, right;
    
    public Node(int x) {
        data = x;
        left = null;
        right = null;
    }
}

class GfG {
    
    static void appendNodes(Node root, int low, int high, List<int> ans) {
        if (root == null) return;
        
        // Current node lies within the required range
        if (root.data >= low && root.data <= high) {
            appendNodes(root.left, low, high, ans);
            ans.Add(root.data);
            appendNodes(root.right, low, high, ans);
        }
        // Current node is smaller than the range
        else if (root.data < low) {
            appendNodes(root.right, low, high, ans);
        }
        // Current node is greater than the range
        else {
            appendNodes(root.left, low, high, ans);
        }
    }
    
    static List<int> nodesInRange(Node root, int low, int high) {
        List<int> ans = new List<int>();
        appendNodes(root, low, high, ans);
        return ans;
    }
    
    static void Main(string[] args) {
        Node root = new Node(22);
        root.left = new Node(12);
        root.right = new Node(30);
        root.left.left = new Node(8);
        root.left.right = new Node(20);
        
        int low = 10, high = 22;
        
        List<int> ans = nodesInRange(root, low, high);
        
        foreach (int x in ans) {
            Console.Write(x + " ");
        }
    }
}
JavaScript
// JavaScript program to find nodes in a BST within a given range

class Node {
    constructor(x) {
        this.data = x;
        this.left = null;
        this.right = null;
    }
}

function appendNodes(root, low, high, ans) {
    if (root === null) return;
    
    // Current node lies within the required range
    if (root.data >= low && root.data <= high) {
        appendNodes(root.left, low, high, ans);
        ans.push(root.data);
        appendNodes(root.right, low, high, ans);
    }
    // Current node is smaller than the range
    else if (root.data < low) {
        appendNodes(root.right, low, high, ans);
    }
    // Current node is greater than the range
    else {
        appendNodes(root.left, low, high, ans);
    }
}

function nodesInRange(root, low, high) {
    let ans = [];
    appendNodes(root, low, high, ans);
    return ans;
}

// Driver code
const root = new Node(22);
root.left = new Node(12);
root.right = new Node(30);
root.left.left = new Node(8);
root.left.right = new Node(20);

const low = 10, high = 22;

const ans = nodesInRange(root, low, high);

console.log(ans.join(' '));

Output
12 20 22 

[Expected Approach] Pruned Morris Traversal - O(n) Time and O(1) Space

Combine BST pruning with Morris traversal. Skip entire left or right subtrees when they fall outside the range. Use threaded traversal to collect only valid nodes without recursion.

  • Initialize curr as root
  • If curr - >data is less than low, move to right subtree
  • If curr - >data is greater than high, move to left subtree
  • Else perform Morris inorder traversal on valid node
  • Use predecessor to create and remove threads
  • Collect current node data only when within range
  • Return answer array
C++
#include <iostream>
#include <vector>
using namespace std;

class Node {
public:
    int data;
    Node *left, *right;

    Node(int x) {
        data = x;
        left = right = nullptr;
    }
};

vector<int> nodesInRange(Node* root, int low, int high) {
    vector<int> ans;
    Node* curr = root;

    while (curr) {

        // Skip entire left subtree
        if (curr->data < low) {
            curr = curr->right;
            continue;
        }

        // Skip entire right subtree
        if (curr->data > high) {
            curr = curr->left;
            continue;
        }

        // Morris Inorder Traversal
        if (curr->left == nullptr) {
            ans.push_back(curr->data);
            curr = curr->right;
        }
        else {
            Node* pre = curr->left;

            while (pre->right && pre->right != curr) {
                pre = pre->right;
            }

            if (pre->right == nullptr) {
                pre->right = curr;
                curr = curr->left;
            }
            else {
                pre->right = nullptr;
                ans.push_back(curr->data);
                curr = curr->right;
            }
        }
    }

    return ans;
}

int main() {
    Node* root = new Node(22);
    root->left = new Node(12);
    root->right = new Node(30);
    root->left->left = new Node(8);
    root->left->right = new Node(20);

    int low = 10, high = 22;

    vector<int> ans = nodesInRange(root, low, high);

    for (int x : ans) {
        cout << x << " ";
    }

    return 0;
}
Java
// Java program to find nodes in BST within range using optimized Morris Traversal
import java.util.*;

class Node {
    int data;
    Node left, right;
    
    Node(int x) {
        data = x;
        left = null;
        right = null;
    }
}

class GfG {
    
    static ArrayList<Integer> nodesInRange(Node root, int low, int high) {
        ArrayList<Integer> ans = new ArrayList<>();
        Node curr = root;
        
        while (curr != null) {
            // Skip entire left subtree
            if (curr.data < low) {
                curr = curr.right;
                continue;
            }
            
            // Skip entire right subtree
            if (curr.data > high) {
                curr = curr.left;
                continue;
            }
            
            // Morris Inorder Traversal
            if (curr.left == null) {
                ans.add(curr.data);
                curr = curr.right;
            } else {
                Node pre = curr.left;
                
                while (pre.right != null && pre.right != curr) {
                    pre = pre.right;
                }
                
                if (pre.right == null) {
                    pre.right = curr;
                    curr = curr.left;
                } else {
                    pre.right = null;
                    ans.add(curr.data);
                    curr = curr.right;
                }
            }
        }
        
        return ans;
    }
    
    public static void main(String[] args) {
        Node root = new Node(22);
        root.left = new Node(12);
        root.right = new Node(30);
        root.left.left = new Node(8);
        root.left.right = new Node(20);
        
        int low = 10, high = 22;
        
        ArrayList<Integer> ans = nodesInRange(root, low, high);
        
        for (int x : ans) {
            System.out.print(x + " ");
        }
    }
}
Python
# Python program to find nodes in BST within range using optimized Morris Traversal

class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None

def nodesInRange(root, low, high):
    ans = []
    curr = root
    
    while curr is not None:
        # Skip entire left subtree
        if curr.data < low:
            curr = curr.right
            continue
        
        # Skip entire right subtree
        if curr.data > high:
            curr = curr.left
            continue
        
        # Morris Inorder Traversal
        if curr.left is None:
            ans.append(curr.data)
            curr = curr.right
        else:
            pre = curr.left
            
            while pre.right is not None and pre.right != curr:
                pre = pre.right
            
            if pre.right is None:
                pre.right = curr
                curr = curr.left
            else:
                pre.right = None
                ans.append(curr.data)
                curr = curr.right
    
    return ans

# Driver code
if __name__ == "__main__":
    root = Node(22)
    root.left = Node(12)
    root.right = Node(30)
    root.left.left = Node(8)
    root.left.right = Node(20)
    
    low, high = 10, 22
    
    ans = nodesInRange(root, low, high)
    
    print(' '.join(map(str, ans)))
C#
// C# program to find nodes in BST within range using optimized Morris Traversal
using System;
using System.Collections.Generic;

class Node {
    public int data;
    public Node left, right;
    
    public Node(int x) {
        data = x;
        left = null;
        right = null;
    }
}

class GfG {
    
    static List<int> nodesInRange(Node root, int low, int high) {
        List<int> ans = new List<int>();
        Node curr = root;
        
        while (curr != null) {
            // Skip entire left subtree
            if (curr.data < low) {
                curr = curr.right;
                continue;
            }
            
            // Skip entire right subtree
            if (curr.data > high) {
                curr = curr.left;
                continue;
            }
            
            // Morris Inorder Traversal
            if (curr.left == null) {
                ans.Add(curr.data);
                curr = curr.right;
            } else {
                Node pre = curr.left;
                
                while (pre.right != null && pre.right != curr) {
                    pre = pre.right;
                }
                
                if (pre.right == null) {
                    pre.right = curr;
                    curr = curr.left;
                } else {
                    pre.right = null;
                    ans.Add(curr.data);
                    curr = curr.right;
                }
            }
        }
        
        return ans;
    }
    
    static void Main(string[] args) {
        Node root = new Node(22);
        root.left = new Node(12);
        root.right = new Node(30);
        root.left.left = new Node(8);
        root.left.right = new Node(20);
        
        int low = 10, high = 22;
        
        List<int> ans = nodesInRange(root, low, high);
        
        foreach (int x in ans) {
            Console.Write(x + " ");
        }
    }
}
JavaScript
// JavaScript program to find nodes in BST within range using optimized Morris Traversal

class Node {
    constructor(x) {
        this.data = x;
        this.left = null;
        this.right = null;
    }
}

function nodesInRange(root, low, high) {
    let ans = [];
    let curr = root;
    
    while (curr !== null) {
        // Skip entire left subtree
        if (curr.data < low) {
            curr = curr.right;
            continue;
        }
        
        // Skip entire right subtree
        if (curr.data > high) {
            curr = curr.left;
            continue;
        }
        
        // Morris Inorder Traversal
        if (curr.left === null) {
            ans.push(curr.data);
            curr = curr.right;
        } else {
            let pre = curr.left;
            
            while (pre.right !== null && pre.right !== curr) {
                pre = pre.right;
            }
            
            if (pre.right === null) {
                pre.right = curr;
                curr = curr.left;
            } else {
                pre.right = null;
                ans.push(curr.data);
                curr = curr.right;
            }
        }
    }
    
    return ans;
}

// Driver code
const root = new Node(22);
root.left = new Node(12);
root.right = new Node(30);
root.left.left = new Node(8);
root.left.right = new Node(20);

const low = 10, high = 22;

const ans = nodesInRange(root, low, high);

console.log(ans.join(' '));

Output
12 20 22 


Comment