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].
Table of Content
[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
#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;
}
// 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 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# 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 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
#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;
}
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 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# 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 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
#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 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 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# 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 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

