Validate if Tree is BST in DSA Go - Time & Space Complexity
We want to know how long it takes to check if a tree follows the rules of a Binary Search Tree (BST).
The question is: how does the time needed grow as the tree gets bigger?
Analyze the time complexity of the following code snippet.
func isBST(node *TreeNode, min, max *int) bool {
if node == nil {
return true
}
if (min != nil && node.Val <= *min) || (max != nil && node.Val >= *max) {
return false
}
return isBST(node.Left, min, &node.Val) && isBST(node.Right, &node.Val, max)
}
This code checks if a binary tree is a BST by verifying each node's value is within allowed min and max limits recursively.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive calls visiting each node once.
- How many times: Once per node in the tree (n times for n nodes).
As the tree grows, the function visits each node once, so the work grows directly with the number of nodes.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 checks |
| 100 | About 100 checks |
| 1000 | About 1000 checks |
Pattern observation: The number of operations grows linearly with the number of nodes.
Time Complexity: O(n)
This means the time to check the tree grows in direct proportion to the number of nodes.
[X] Wrong: "The check is faster because it stops early if a node fails, so it's less than O(n)."
[OK] Correct: While it may stop early sometimes, in the worst case it must check every node, so the time complexity is still O(n).
Understanding this time complexity helps you explain how efficient your tree checks are and shows you can reason about recursive algorithms clearly.
"What if we changed the code to use an in-order traversal and check if values are sorted? How would the time complexity change?"
Practice
Solution
Step 1: Understand BST property
A BST requires that for each node, all values in the left subtree are less than the node's value, and all values in the right subtree are greater.Step 2: Compare options with definition
Every node's left subtree contains values less than the node, and right subtree contains values greater. matches the BST property exactly, while others describe different tree properties.Final Answer:
Every node's left subtree contains values less than the node, and right subtree contains values greater. -> Option DQuick Check:
BST property = Every node's left subtree contains values less than the node, and right subtree contains values greater. [OK]
- Confusing BST with balanced tree
- Thinking all nodes must have two children
- Assuming all values are equal
Solution
Step 1: Identify correct parameter and return types
The function should accept a pointer to the root node (to avoid copying) and return a boolean indicating if the tree is BST.Step 2: Match with options
func isBST(root *Node) bool matches this: it takes *Node and returns bool. Others have wrong parameter types or return types.Final Answer:
func isBST(root *Node) bool -> Option AQuick Check:
Pointer input + bool output = func isBST(root *Node) bool [OK]
- Passing Node by value instead of pointer
- Returning int or string instead of bool
- Using void (no return) for validation function
package main
import "fmt"
type Node struct {
Val int
Left *Node
Right *Node
}
func isBSTUtil(node *Node, min, max int) bool {
if node == nil {
return true
}
if node.Val <= min || node.Val >= max {
return false
}
return isBSTUtil(node.Left, min, node.Val) && isBSTUtil(node.Right, node.Val, max)
}
func isBST(root *Node) bool {
return isBSTUtil(root, -1000, 1000)
}
func main() {
root := &Node{Val: 10}
root.Left = &Node{Val: 5}
root.Right = &Node{Val: 15}
root.Right.Left = &Node{Val: 6}
root.Right.Right = &Node{Val: 20}
fmt.Println(isBST(root))
}Solution
Step 1: Trace tree values against BST rules
The node with value 6 is in the right subtree of 10 but less than 10, violating BST property.Step 2: Check isBSTUtil logic
isBSTUtil checks if node.Val is within (min, max). For node 6, min=10, max=15, but 6 <= 10 fails the condition, returning false.Final Answer:
false -> Option AQuick Check:
6 in right subtree < 10 = false [OK]
- Ignoring subtree value constraints
- Assuming all nodes in right subtree are greater than root only
- Not updating min/max bounds during recursion
func isBST(node *Node) bool {
if node == nil {
return true
}
if node.Left != nil && node.Left.Val > node.Val {
return false
}
if node.Right != nil && node.Right.Val < node.Val {
return false
}
return isBST(node.Left) && isBST(node.Right)
}Solution
Step 1: Analyze comparison logic
The function compares only node.Left.Val and node.Right.Val with node.Val, ignoring entire subtree values.Step 2: Understand BST violation cases
A violation can occur deeper in subtrees, e.g., a left subtree node greater than root, which this function misses.Final Answer:
It only compares immediate children, missing deeper subtree violations. -> Option BQuick Check:
Check all subtree nodes, not just immediate children [OK]
- Checking only immediate children values
- Not passing min/max bounds in recursion
- Assuming local checks guarantee global BST
Solution
Step 1: Understand duplicate placement in BST
Duplicates allowed only on right means left subtree nodes must be strictly less than node.Val, right subtree nodes can be equal or greater.Step 2: Adjust min/max conditions accordingly
Change violation check to (node.Val <= min || node.Val > max), enforcing node.Val > min && node.Val <= max. This allows equality to max (parent.Val in right calls) but enforces > min (parent.Val in left calls).Final Answer:
Allow duplicates only if node.Val > min for left subtree and node.Val <= max for right subtree. -> Option CQuick Check:
> min && <= max = duplicates on right only [OK]
- Allowing duplicates on left subtree
- Not adjusting inequality signs properly
- Allowing duplicates on both sides without rules
Ready to prove it?
Pass the test and this pattern moves unknown
