Print BST keys in given Range | O(1) Space
Last Updated : 22 Oct, 2024
Given two values n1 and n2 where n1 < n2 and a root pointer to a Binary Search Tree. The task is to find all the keys of the tree in the range n1 to n2 in increasing order.
Examples:
Input: n1 = 10 , n2 = 22
Output: 12, 20 and 22.
Explanation: The keys are 4, 8, 12, 20, and 22, So keys in range 10 to 22 is 12, 20 and 22.
Input: n1 = 1 , n2 = 10
Output: 8
Explanation: The key 8 is in the range 1 to 10
Inorder traversal uses recursion or stack/queue which consumes O(n) space. But there is one efficient way to do inorder tree traversal using Morris traversal which is based in Threaded binary trees. Morris traversal uses no recursion or stack/queue and simply stores some important information in the wasted NULL pointers. Morris traversal consumes constant extra memory O(1) as it uses no recursion or stack/queue. Hence we will use Morris traversal to do inorder traversal in the algorithm presented in this tutorial to print keys of a BST in a given range, which is efficient memory-wise.
The concept of Threaded Binary trees is simple in that they store some useful information in the wasted NULL pointers. In a normal binary tree with n nodes, n+1 NULL pointers waste memory.
Approach:
The idea is to use Morris Traversal Algorithm to perform in-order traversal of the binary tree. Morris traversal can be used in solving problems where inorder tree traversals are used especially in order statistics eg - Kth largest element in BST, Kth smallest in BST etc. Hence, this is where Morris traversal would come handy as a more efficient method to do inorder traversal in constant O(1) space without using any stack or recursion.
Step by step approach:
- Initialize the current node as root.
- While current is not null, check if it has a left child.
- If there is no left child, append the current node if it lies in the given range and move to the right child of the current node.
- Otherwise, find the rightmost node of the left subtree or the node whose right child is the current node.
- If the right child is NULL, make current as the right child and move to the left child of current.
- If the right child is the current node itself, append the current node if it lies in the given range, make the right child NULL and move to the right child of the current node.
C++ // C++ prgram to print BST in a given range #include <bits/stdc++.h> using namespace std; class Node { public: int data; Node *left, *right; Node (int x) { data = x; left = nullptr; right = nullptr; } }; // Function to print nodes // that lie in the range. vector<int> printNearNodes(Node *root, int low, int high) { vector<int> ans; Node* curr = root; while (curr != nullptr) { // if left child is null, check // curr node and move to right node. if (curr->left == nullptr) { if (curr->data>=low && curr->data<=high) ans.push_back(curr->data); curr = curr->right; } else { // Find the inorder predecessor of curr Node* pre = curr->left; while (pre->right != nullptr && pre->right != curr) pre = pre->right; // Make curr as the right child of its // inorder predecessor and move to // left node. if (pre->right == nullptr) { pre->right = curr; curr = curr->left; } // Revert the changes made in the 'if' part to // restore the original tree i.e., fix the right // child of predecessor else { pre->right = nullptr; if (curr->data>=low && curr->data<=high) ans.push_back(curr->data); curr = curr->right; } } } return ans; } int main() { // BST // 22 // / \ // 12 30 // / \ // 8 20 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 n1 = 10, n2 = 22; vector<int> ans = printNearNodes(root, n1, n2); for (auto num: ans) cout << num << " "; return 0; }
Java // Java program to print BST in a given range import java.util.ArrayList; class Node { int data; Node left, right; Node(int x) { data = x; left = null; right = null; } } class GfG { // Function to print nodes // that lie in the range. static ArrayList<Integer> printNearNodes (Node root, int low, int high) { ArrayList<Integer> ans = new ArrayList<>(); Node curr = root; while (curr != null) { // if left child is null, check // curr node and move to right node. if (curr.left == null) { if (curr.data >= low && curr.data <= high) ans.add(curr.data); curr = curr.right; } else { // Find the inorder predecessor of curr Node pre = curr.left; while (pre.right != null && pre.right != curr) pre = pre.right; // Make curr as the right child of its // inorder predecessor and move to // left node. if (pre.right == null) { pre.right = curr; curr = curr.left; } // Revert the changes made in the 'if' part to // restore the original tree i.e., fix the right // child of predecessor else { pre.right = null; if (curr.data >= low && curr.data <= high) ans.add(curr.data); curr = curr.right; } } } return ans; } public static void main(String[] args) { // BST // 22 // / \ // 12 30 // / \ // 8 20 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 n1 = 10, n2 = 22; ArrayList<Integer> ans = printNearNodes(root, n1, n2); for (int num : ans) { System.out.print(num + " "); } } }
Python # Python program to print BST in a given range class Node: def __init__(self, x): self.data = x self.left = None self.right = None # Function to print nodes # that lie in the range. def printNearNodes(root, low, high): ans = [] curr = root while curr is not None: # if left child is null, check # curr node and move to right node. if curr.left is None: if low <= curr.data <= high: ans.append(curr.data) curr = curr.right else: # Find the inorder predecessor of curr pre = curr.left while pre.right is not None and pre.right != curr: pre = pre.right # Make curr as the right child of its # inorder predecessor and move to # left node. if pre.right is None: pre.right = curr curr = curr.left else: pre.right = None if low <= curr.data <= high: ans.append(curr.data) curr = curr.right return ans if __name__ == "__main__": # BST # 22 # / \ # 12 30 # / \ # 8 20 root = Node(22) root.left = Node(12) root.right = Node(30) root.left.left = Node(8) root.left.right = Node(20) n1, n2 = 10, 22 ans = printNearNodes(root, n1, n2) print(" ".join(map(str, ans)))
C# // C# program to print BST in 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 { // Function to print nodes // that lie in the range. static List<int> printNearNodes (Node root, int low, int high) { List<int> ans = new List<int>(); Node curr = root; while (curr != null) { // if left child is null, check // curr node and move to right node. if (curr.left == null) { if (curr.data >= low && curr.data <= high) ans.Add(curr.data); curr = curr.right; } else { // Find the inorder predecessor of curr Node pre = curr.left; while (pre.right != null && pre.right != curr) pre = pre.right; // Make curr as the right child of its // inorder predecessor and move to // left node. if (pre.right == null) { pre.right = curr; curr = curr.left; } // Revert the changes made in the 'if' part to // restore the original tree i.e., fix the right // child of predecessor else { pre.right = null; if (curr.data >= low && curr.data <= high) ans.Add(curr.data); curr = curr.right; } } } return ans; } static void Main(string[] args) { // BST // 22 // / \ // 12 30 // / \ // 8 20 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 n1 = 10, n2 = 22; List<int> ans = printNearNodes(root, n1, n2); foreach (int num in ans) { Console.Write(num + " "); } } }
JavaScript // JavaScript program to print BST in a given range class Node { constructor(x) { this.data = x; this.left = null; this.right = null; } } // Function to print nodes // that lie in the range. function printNearNodes(root, low, high) { let ans = []; let curr = root; while (curr !== null) { // if left child is null, check // curr node and move to right node. if (curr.left === null) { if (curr.data >= low && curr.data <= high) ans.push(curr.data); curr = curr.right; } else { // Find the inorder predecessor of curr let pre = curr.left; while (pre.right !== null && pre.right !== curr) pre = pre.right; // Make curr as the right child of its // inorder predecessor and move to // left node. if (pre.right === null) { pre.right = curr; curr = curr.left; } // Revert the changes made in the 'if' part to // restore the original tree i.e., fix the right // child of predecessor else { pre.right = null; if (curr.data >= low && curr.data <= high) ans.push(curr.data); curr = curr.right; } } } return ans; } // BST // 22 // / \ // 12 30 // / \ // 8 20 let 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); let n1 = 10, n2 = 22; let ans = printNearNodes(root, n1, n2); console.log(ans.join(" "));
Time Complexity: O(n), where n is the number of nodes in the binary tree.
Auxiliary Space: O(1), since no extra space has been taken.
Related article:
Similar Reads
Binary Search Tree A Binary Search Tree (BST) is a type of binary tree data structure in which each node contains a unique key and satisfies a specific ordering property:All nodes in the left subtree of a node contain values strictly less than the nodeâs value. All nodes in the right subtree of a node contain values s
4 min read
Introduction to Binary Search Tree Binary Search Tree is a data structure used in computer science for organizing and storing data in a sorted manner. Binary search tree follows all properties of binary tree and for every nodes, its left subtree contains values less than the node and the right subtree contains values greater than the
3 min read
Applications of BST Binary Search Tree (BST) is a data structure that is commonly used to implement efficient searching, insertion, and deletion operations along with maintaining sorted sequence of data. Please remember the following properties of BSTs before moving forward.The left subtree of a node contains only node
3 min read
Applications, Advantages and Disadvantages of Binary Search Tree A Binary Search Tree (BST) is a data structure used to storing data in a sorted manner. Each node in a Binary Search Tree has at most two children, a left child and a right child, with the left child containing values less than the parent node and the right child containing values greater than the p
2 min read
Insertion in Binary Search Tree (BST) Given a BST, the task is to insert a new node in this BST.Example: How to Insert a value in a Binary Search Tree:A new key is always inserted at the leaf by maintaining the property of the binary search tree. We start searching for a key from the root until we hit a leaf node. Once a leaf node is fo
15 min read
Searching in Binary Search Tree (BST) Given a BST, the task is to search a node in this BST. For searching a value in BST, consider it as a sorted array. Now we can easily perform search operation in BST using Binary Search Algorithm. Input: Root of the below BST Output: TrueExplanation: 8 is present in the BST as right child of rootInp
7 min read
Deletion in Binary Search Tree (BST) Given a BST, the task is to delete a node in this BST, which can be broken down into 3 scenarios:Case 1. Delete a Leaf Node in BST Case 2. Delete a Node with Single Child in BSTDeleting a single child node is also simple in BST. Copy the child to the node and delete the node. Case 3. Delete a Node w
10 min read
Binary Search Tree (BST) Traversals â Inorder, Preorder, Post Order Given a Binary Search Tree, The task is to print the elements in inorder, preorder, and postorder traversal of the Binary Search Tree. Input: A Binary Search TreeOutput: Inorder Traversal: 10 20 30 100 150 200 300Preorder Traversal: 100 20 10 30 200 150 300Postorder Traversal: 10 30 20 150 300 200 1
10 min read
Balance a Binary Search Tree Given a BST (Binary Search Tree) that may be unbalanced, the task is to convert it into a balanced BST that has the minimum possible height.Examples: Input: Output: Explanation: The above unbalanced BST is converted to balanced with the minimum possible height.Input: Output: Explanation: The above u
10 min read
Self-Balancing Binary Search Trees Self-Balancing Binary Search Trees are height-balanced binary search trees that automatically keep the height as small as possible when insertion and deletion operations are performed on the tree. The height is typically maintained in order of logN so that all operations take O(logN) time on average
4 min read