Floor and Ceil in BST in DSA Go - Time & Space Complexity
We want to know how long it takes to find the floor or ceil of a value in a Binary Search Tree (BST).
How does the search time grow as the tree gets bigger?
Analyze the time complexity of the following code snippet.
func floorBST(root *Node, key int) *Node {
var floorNode *Node
current := root
for current != nil {
if current.val == key {
return current
} else if current.val > key {
current = current.left
} else {
floorNode = current
current = current.right
}
}
return floorNode
}
This code finds the floor value (largest value less than or equal to key) in a BST by walking down the tree.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Traversing down the BST nodes one by one.
- How many times: At most once per level of the tree, from root to leaf.
As the BST grows, the search path length depends on the tree height.
| Input Size (n) | Approx. Operations (steps down tree) |
|---|---|
| 10 | About 3 to 4 |
| 100 | About 6 to 7 |
| 1000 | About 9 to 10 |
Pattern observation: The number of steps grows slowly, roughly proportional to the tree height, not the total nodes.
Time Complexity: O(h)
This means the time depends on the height of the BST, which is the longest path from root to leaf.
[X] Wrong: "Finding floor or ceil always takes O(n) time because we might check every node."
[OK] Correct: The BST structure lets us skip large parts of the tree, so we only follow one path down, not all nodes.
Understanding how BST height affects search time helps you explain why balanced trees are faster and shows you can analyze real code efficiently.
"What if the BST is perfectly balanced versus completely skewed? How would the time complexity change?"
Practice
floor of a value in a Binary Search Tree (BST) represent?Solution
Step 1: Understand the floor concept in BST
The floor of a value is the largest value in the BST that is less than or equal to the given value.Step 2: Compare with options
The greatest value in the BST less than or equal to the given value matches this definition exactly, while others describe different concepts.Final Answer:
The greatest value in the BST less than or equal to the given value -> Option DQuick Check:
Floor = greatest ≤ value [OK]
- Confusing floor with ceil
- Thinking floor is smallest value
- Assuming floor is always root
Solution
Step 1: Check parameter order and types
The function should take a pointer to the root node and an integer key to search for ceil.Step 2: Validate options
func ceil(root *Node, key int) intuses pointer to Node and int key in correct order. Swapping parameters to key first is wrong, using value Node instead of pointer is wrong, using string for key is wrong.Final Answer:
func ceil(root *Node, key int) int -> Option AQuick Check:
Pointer root and int key correct [OK]
- Swapping parameter order
- Using value instead of pointer for root
- Wrong key data type
type Node struct {
val int
left, right *Node
}
func ceil(root *Node, key int) int {
if root == nil {
return -1
}
if root.val == key {
return root.val
}
if root.val < key {
return ceil(root.right, key)
}
ceilVal := ceil(root.left, key)
if ceilVal >= key && ceilVal != -1 {
return ceilVal
}
return root.val
}
// BST structure:
// 10
// / \
// 5 15
// / \
// 12 20
// Call: ceil(root, 14)Solution
Step 1: Trace ceil function with key=14
Start at root 10: 10 < 14, go right to 15. 15 > 14, check left subtree of 15 (12). 12 < 14, so ceil(12) returns -1, so return 15.Step 2: Confirm returned ceil value
Ceil is 15, the smallest value ≥ 14 in BST.Final Answer:
15 -> Option AQuick Check:
Ceil(14) = 15 [OK]
- Returning 12 instead of 15
- Returning -1 when ceil exists
- Confusing floor and ceil logic
func floor(root *Node, key int) int {
if root == nil {
return -1
}
if root.val == key {
return root.val
}
if root.val > key {
return floor(root.left, key)
}
floorVal := floor(root.right, key)
if floorVal <= key {
return floorVal
}
return root.val
}Solution
Step 1: Analyze floorVal condition
The code checks if floorVal <= key, but floorVal can be -1 (no floor found). This causes wrong returns.Step 2: Correct condition for valid floorVal
It should check if floorVal != -1 to confirm a valid floor before returning it; otherwise return root.val.Final Answer:
The condition 'floorVal <= key' should be 'floorVal != -1' -> Option BQuick Check:
Check floorVal != -1 before return [OK]
- Ignoring -1 as invalid floor
- Wrong comparison operators
- Changing base case return value
Solution
Step 1: Understand single traversal for floor and ceil
During one traversal, compare node values with key. Update floor if node.val ≤ key and is greater than current floor. Update ceil if node.val ≥ key and is less than current ceil.Step 2: Compare approaches
Traverse once, update floor when node.val ≤ key, update ceil when node.val ≥ key efficiently finds both in one pass. Options B and C require multiple traversals. Use inorder traversal and store all nodes in array, then binary search uses extra space and is less efficient.Final Answer:
Traverse once, update floor when node.val ≤ key, update ceil when node.val ≥ key -> Option CQuick Check:
Single pass update floor & ceil [OK]
- Doing separate traversals for floor and ceil
- Using extra space unnecessarily
- Restarting traversal multiple times
Ready to prove it?
Pass the test and this pattern moves unknown
