BST Property and Why It Matters in DSA C++ - Time & Space Complexity
We want to understand how the special rule of a Binary Search Tree (BST) affects how fast we can find or add items.
How does this rule help us work faster as the tree grows?
Analyze the time complexity of the following code snippet.
// Check if a value exists in a BST
bool searchBST(TreeNode* root, int val) {
if (!root) return false;
if (root->val == val) return true;
if (val < root->val) return searchBST(root->left, val);
else return searchBST(root->right, val);
}
This code searches for a value in a BST by following the BST property to decide which side to search next.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive calls moving down one level of the tree.
- How many times: At most once per tree level until the value is found or a leaf is reached.
Each step moves down one level, so the number of steps depends on the tree's height.
| Input Size (n) | Approx. Operations (steps down tree) |
|---|---|
| 10 | About 4 steps |
| 100 | About 7 steps |
| 1000 | About 10 steps |
Pattern observation: The steps grow slowly, roughly with the height of the tree, not the total number of nodes.
Time Complexity: O(h) where h is the tree height
This means the search time depends on how tall the tree is, not just how many items it has.
[X] Wrong: "Searching a BST always takes the same time as searching a balanced tree."
[OK] Correct: If the tree is unbalanced (like a linked list), the height can be as big as the number of nodes, making search slow.
Knowing how the BST property affects search speed helps you explain why balanced trees matter and shows you understand efficient data access.
"What if we changed the BST to a balanced tree like an AVL tree? How would the time complexity change?"
Practice
Solution
Step 1: Understand BST definition
A BST requires that for every node, values in the left subtree are smaller and values in the right subtree are larger.Step 2: Compare options with BST property
For each node, all values in the left subtree are smaller, and all values in the right subtree are larger. matches the BST property exactly, while others describe different tree types or incorrect properties.Final Answer:
For each node, all values in the left subtree are smaller, and all values in the right subtree are larger. -> Option AQuick Check:
BST property = For each node, all values in the left subtree are smaller, and all values in the right subtree are larger. [OK]
- Thinking BST means every node has two children
- Confusing BST with balanced or complete trees
- Assuming all nodes have the same value
Solution
Step 1: Check pointer usage in node declaration
BST nodes must use pointers for left and right children to allow dynamic linking.Step 2: Compare struct and class syntax
struct Node { int data; Node* left; Node* right; }; correctly uses struct with pointers. class Node { int data; Node* left; Node* right; }; uses class but misses access specifiers (defaults private). Declarations using objects instead of pointers for children are incorrect.Final Answer:
struct Node { int data; Node* left; Node* right; }; -> Option CQuick Check:
Use pointers for children in BST node [OK]
- Using objects instead of pointers for children
- Forgetting semicolon after struct
- Using class without public access for members
struct Node {
int data;
Node* left;
Node* right;
};
Node* insert(Node* root, int val) {
if (!root) {
Node* newNode = new Node{val, nullptr, nullptr};
return newNode;
}
if (val < root->data) root->left = insert(root->left, val);
else root->right = insert(root->right, val);
return root;
}
int main() {
Node* root = nullptr;
root = insert(root, 10);
root = insert(root, 5);
root = insert(root, 15);
root = insert(root, 12);
root = insert(root, 18);
return 0;
}
What is the in-order traversal output of the BST after these insertions?Solution
Step 1: Understand insertion order and BST structure
Inserted values: 10 (root), 5 (left), 15 (right), 12 (left of 15), 18 (right of 15).Step 2: Perform in-order traversal (left, root, right)
Traverse left subtree: 5, root: 10, left of right subtree: 12, root of right subtree: 15, right of right subtree: 18. So output is [5, 10, 12, 15, 18].Final Answer:
[5, 10, 12, 15, 18] -> Option DQuick Check:
In-order traversal of BST = sorted values [OK]
- Confusing pre-order or post-order with in-order
- Ignoring BST insertion rules
- Mixing up left and right subtree traversal
Node* insert(Node* root, int val) {
if (root == nullptr) {
Node* newNode = new Node{val, nullptr, nullptr};
return newNode;
}
if (val <= root->data) root->left = insert(root->left, val);
else root->right = insert(root->right, val);
return root;
}
What is the main issue with this code regarding BST property?Solution
Step 1: Analyze the condition for left subtree insertion
The code uses val <= root->data to decide left subtree insertion, allowing duplicates on the left.Step 2: Understand BST strict property
Strict BST property requires all left subtree values to be strictly less than the node's value. Allowing duplicates on left can break this.Final Answer:
Using <= allows duplicate values on the left, which may violate strict BST property. -> Option BQuick Check:
Strict BST: left < node < right [OK]
- Ignoring duplicate handling in BST
- Thinking recursion causes infinite loops here
- Assuming null root case is missing
Solution
Step 1: Recall BST in-order traversal property
In-order traversal visits nodes in ascending order for BST.Step 2: Use in-order traversal to find kth smallest
By traversing in-order and counting nodes, we can stop at kth node, efficiently finding kth smallest.Final Answer:
Perform an in-order traversal and stop when the kth element is reached. -> Option AQuick Check:
In-order traversal = sorted order [OK]
- Using level-order which is not sorted
- Traversing only right subtree misses smaller values
- Sorting after pre-order wastes time
Ready to prove it?
Pass the test and this pattern moves unknown
