Given a Binary search Tree that contains positive integer values greater than 0. The task is to check whether the BST contains a dead end or not. Here Dead End means, insertion of any positive integer element is not possible after that node.
Examples:Â Â
Input: root[] = [8, 5, 9, 2, 7, N, N, 1]
Output: true
Explanation: Node 1 is a Dead End in the given BST. We can neither insert 0 as only positives are allowed not insert 3 (because 3 cannot be inserted as left of 2)Input: root[] = [8, 7, 10, 2, N, 9, 13]
Output: true
Explanation: Node 9 is a Dead End in the given BST.
Table of Content
Observation:
Since BSTs typically contain only positive integers greater than 0, a node becomes a dead end when both of its adjacent values that is, (value - 1) and (value + 1) — are already present in the tree. In such cases, no new node can be inserted in that position while maintaining the BST's structural rules.
[Naive Approach] Using Recursion - O(n * h) time and O(h) space
The idea is to iterate through each leaf node and check whether the values
value - 1andvalue + 1exist in the tree. If both of these values are present, it indicates a dead end, and the function returnstrue. This check is performed recursively while traversing the tree.
// C++ program to Check whether BST contains Dead End or not
#include <bits/stdc++.h>
using namespace std;
class Node {
public:
int data;
Node *left, *right;
Node(int val){
data = val;
left = nullptr;
right = nullptr;
}
};
bool findVal(Node* root, int val) {
// For non-positive values, return true
// (as these values cannot be inserted)
if (val <= 0) return true;
if (root == nullptr) return false;
if (root->data == val) return true;
else if (root->data < val) return findVal(root->right, val);
return findVal(root->left, val);
}
bool dfs(Node* curr, Node* root) {
// Base Case
if (curr == nullptr) return false;
// If value val - 1 and val + 1 already
// exists in the tree, and this node is
// a leaf node, return true.
if (curr->left == nullptr && curr->right == nullptr) {
int val = curr->data;
return findVal(root, val-1) && findVal(root, val+1);
}
return dfs(curr->left, root) || dfs(curr->right, root);
}
bool isDeadEnd(Node *root) {
return dfs(root, root);
}
int main() {
Node* root = new Node(8);
root->left = new Node(5);
root->right = new Node(9);
root->left->left = new Node(2);
root->left->right = new Node(7);
root->left->left->left = new Node(1);
if (isDeadEnd(root)) {
cout << "true" << endl;
} else {
cout << "false" << endl;
}
return 0;
}
// Java program to Check whether BST contains Dead End or not
class Node {
int data;
Node left, right;
Node(int val) {
data = val;
left = null;
right = null;
}
}
class GfG {
static boolean findVal(Node root, int val) {
// For non-positive values, return true
// (as these values cannot be inserted)
if (val <= 0) return true;
if (root == null) return false;
if (root.data == val) return true;
else if (root.data < val) return findVal(root.right, val);
return findVal(root.left, val);
}
static boolean dfs(Node curr, Node root) {
// Base Case
if (curr == null) return false;
// If value val - 1 and val + 1 already
// exists in the tree, and this node is
// a leaf node, return true.
if (curr.left == null && curr.right == null) {
int val = curr.data;
return findVal(root, val-1) && findVal(root, val+1);
}
return dfs(curr.left, root) || dfs(curr.right, root);
}
static boolean isDeadEnd(Node root) {
return dfs(root, root);
}
public static void main(String[] args) {
Node root = new Node(8);
root.left = new Node(5);
root.right = new Node(9);
root.left.left = new Node(2);
root.left.right = new Node(7);
root.left.left.left = new Node(1);
System.out.println(isDeadEnd(root));
}
}
# Python program to Check whether BST contains Dead End or not
class Node:
def __init__(self, val):
self.data = val
self.left = None
self.right = None
def findVal(root, val):
# For non-positive values, return true
# (as these values cannot be inserted)
if val <= 0:
return True
if root is None:
return False
if root.data == val:
return True
elif root.data < val:
return findVal(root.right, val)
return findVal(root.left, val)
def dfs(curr, root):
# Base Case
if curr is None:
return False
# If value val - 1 and val + 1 already
# exists in the tree, and this node is
# a leaf node, return true.
if curr.left is None and curr.right is None:
val = curr.data
return findVal(root, val-1) and findVal(root, val+1)
return dfs(curr.left, root) or dfs(curr.right, root)
def isDeadEnd(root):
return dfs(root, root)
if __name__ == "__main__":
root = Node(8)
root.left = Node(5)
root.right = Node(9)
root.left.left = Node(2)
root.left.right = Node(7)
root.left.left.left = Node(1)
if isDeadEnd(root):
print("true")
else:
print("false")
// C# program to Check whether BST contains Dead End or not
using System;
class Node {
public int data;
public Node left, right;
public Node(int val) {
data = val;
left = null;
right = null;
}
}
class GfG {
static bool FindVal(Node root, int val) {
// For non-positive values, return true
// (as these values cannot be inserted)
if (val <= 0) return true;
if (root == null) return false;
if (root.data == val) return true;
else if (root.data < val) return FindVal(root.right, val);
return FindVal(root.left, val);
}
static bool Dfs(Node curr, Node root) {
// Base Case
if (curr == null) return false;
// If value val - 1 and val + 1 already
// exists in the tree, and this node is
// a leaf node, return true.
if (curr.left == null && curr.right == null) {
int val = curr.data;
return FindVal(root, val-1) && FindVal(root, val+1);
}
return Dfs(curr.left, root) || Dfs(curr.right, root);
}
static bool IsDeadEnd(Node root) {
return Dfs(root, root);
}
static void Main() {
Node root = new Node(8);
root.left = new Node(5);
root.right = new Node(9);
root.left.left = new Node(2);
root.left.right = new Node(7);
root.left.left.left = new Node(1);
if (IsDeadEnd(root)) {
Console.WriteLine("true");
} else {
Console.WriteLine("false");
}
}
}
// JavaScript program to Check whether BST contains Dead End or not
class Node {
constructor(val) {
this.data = val;
this.left = null;
this.right = null;
}
}
function findVal(root, val) {
// For non-positive values, return true
// (as these values cannot be inserted)
if (val <= 0) return true;
if (root === null) return false;
if (root.data === val) return true;
else if (root.data < val) return findVal(root.right, val);
return findVal(root.left, val);
}
function dfs(curr, root) {
// Base Case
if (curr === null) return false;
// If value val - 1 and val + 1 already
// exists in the tree, and this node is
// a leaf node, return true.
if (curr.left === null && curr.right === null) {
let val = curr.data;
return findVal(root, val-1) && findVal(root, val+1);
}
return dfs(curr.left, root) || dfs(curr.right, root);
}
function isDeadEnd(root) {
return dfs(root, root);
}
// Driver Code
let root = new Node(8);
root.left = new Node(5);
root.right = new Node(9);
root.left.left = new Node(2);
root.left.right = new Node(7);
root.left.left.left = new Node(1);
if (isDeadEnd(root)) {
console.log("true");
} else {
console.log("false");
}
Output
true
[Better Approach] Using Hash Set - O(n) time and O(n) space
The idea is to store all node values in a set and then traverse the tree again to identify leaf nodes. For each leaf node, check if both (value - 1) and (value + 1) exist in the same set. If yes, it indicates a dead end.
- Traverse the BST and insert each node value into a set for all nodes.
- Traverse again, and for every leaf value check, check if both (value - 1) and (value + 1) exist in the set.
- If such a condition is found for any leaf node, return true. Else, return false.
// C++ program to Check whether BST contains Dead End or not
#include <bits/stdc++.h>
using namespace std;
class Node {
public:
int data;
Node *left, *right;
Node(int val){
data = val;
left = nullptr;
right = nullptr;
}
};
// Recursive function to insert all nodes
// into a hash set.
void storeAllNodes(Node* root, unordered_set<int>& nodeSet) {
if (!root) return;
nodeSet.insert(root->data);
storeAllNodes(root->left, nodeSet);
storeAllNodes(root->right, nodeSet);
}
// Recursive function to check if a leaf node
// is dead end or not.
bool deadEndRecur(Node* root, unordered_set<int>& nodeSet) {
if (!root) return false;
// Check leaf node is dead end or not.
if (!root->left && !root->right) {
int val = root->data;
if (nodeSet.count(val - 1) && nodeSet.count(val + 1))
return true;
}
return deadEndRecur(root->left, nodeSet) ||
deadEndRecur(root->right, nodeSet);
}
bool isDeadEnd(Node *root) {
unordered_set<int> nodeSet;
// to handle case when node value is 1
nodeSet.insert(0);
storeAllNodes(root, nodeSet);
return deadEndRecur(root, nodeSet);
}
int main() {
Node* root = new Node(8);
root->left = new Node(5);
root->right = new Node(9);
root->left->left = new Node(2);
root->left->right = new Node(7);
root->left->left->left = new Node(1);
if (isDeadEnd(root)) {
cout << "true" << endl;
} else {
cout << "false" << endl;
}
return 0;
}
// Java program to Check whether BST contains Dead End or not
import java.util.HashSet;
import java.util.Set;
class Node {
int data;
Node left, right;
Node(int val) {
data = val;
left = null;
right = null;
}
}
class GfG {
// Recursive function to insert all nodes
// into a hash set.
static void storeAllNodes(Node root, Set<Integer> nodeSet) {
if (root == null) return;
nodeSet.add(root.data);
storeAllNodes(root.left, nodeSet);
storeAllNodes(root.right, nodeSet);
}
// Recursive function to check if a leaf node
// is dead end or not.
static boolean deadEndRecur(Node root, Set<Integer> nodeSet) {
if (root == null) return false;
// Check leaf node is dead end or not.
if (root.left == null && root.right == null) {
int val = root.data;
if (nodeSet.contains(val - 1) && nodeSet.contains(val + 1))
return true;
}
return deadEndRecur(root.left, nodeSet) ||
deadEndRecur(root.right, nodeSet);
}
static boolean isDeadEnd(Node root) {
Set<Integer> nodeSet = new HashSet<>();
// to handle case when node value is 1
nodeSet.add(0);
storeAllNodes(root, nodeSet);
return deadEndRecur(root, nodeSet);
}
public static void main(String[] args) {
Node root = new Node(8);
root.left = new Node(5);
root.right = new Node(9);
root.left.left = new Node(2);
root.left.right = new Node(7);
root.left.left.left = new Node(1);
System.out.println(isDeadEnd(root));
}
}
# Python program to Check whether BST contains Dead End or not
class Node:
def __init__(self, val):
self.data = val
self.left = None
self.right = None
# Recursive function to insert all nodes
# into a hash set.
def storeAllNodes(root, nodeSet):
if not root:
return
nodeSet.add(root.data)
storeAllNodes(root.left, nodeSet)
storeAllNodes(root.right, nodeSet)
# Recursive function to check if a leaf node
# is dead end or not.
def deadEndRecur(root, nodeSet):
if not root:
return False
# Check leaf node is dead end or not.
if not root.left and not root.right:
val = root.data
if (val - 1 in nodeSet) and (val + 1 in nodeSet):
return True
return deadEndRecur(root.left, nodeSet) or \
deadEndRecur(root.right, nodeSet)
def isDeadEnd(root):
nodeSet = set()
# to handle case when node value is 1
nodeSet.add(0)
storeAllNodes(root, nodeSet)
return deadEndRecur(root, nodeSet)
if __name__ == "__main__":
root = Node(8)
root.left = Node(5)
root.right = Node(9)
root.left.left = Node(2)
root.left.right = Node(7)
root.left.left.left = Node(1)
if isDeadEnd(root):
print("true")
else:
print("false")
// C# program to Check whether BST contains Dead End or not
using System;
using System.Collections.Generic;
class Node {
public int data;
public Node left, right;
public Node(int val) {
data = val;
left = null;
right = null;
}
}
class GfG {
// Recursive function to insert all nodes
// into a hash set.
static void storeAllNodes(Node root, HashSet<int> nodeSet) {
if (root == null) return;
nodeSet.Add(root.data);
storeAllNodes(root.left, nodeSet);
storeAllNodes(root.right, nodeSet);
}
// Recursive function to check if a leaf node
// is dead end or not.
static bool deadEndRecur(Node root, HashSet<int> nodeSet) {
if (root == null) return false;
// Check leaf node is dead end or not.
if (root.left == null && root.right == null) {
int val = root.data;
if (nodeSet.Contains(val - 1) && nodeSet.Contains(val + 1))
return true;
}
return deadEndRecur(root.left, nodeSet) ||
deadEndRecur(root.right, nodeSet);
}
static bool isDeadEnd(Node root) {
HashSet<int> nodeSet = new HashSet<int>();
// to handle case when node value is 1
nodeSet.Add(0);
storeAllNodes(root, nodeSet);
return deadEndRecur(root, nodeSet);
}
static void Main() {
Node root = new Node(8);
root.left = new Node(5);
root.right = new Node(9);
root.left.left = new Node(2);
root.left.right = new Node(7);
root.left.left.left = new Node(1);
if (isDeadEnd(root)) {
Console.WriteLine("true");
} else {
Console.WriteLine("false");
}
}
}
// JavaScript program to Check whether BST contains Dead End or not
class Node {
constructor(val) {
this.data = val;
this.left = null;
this.right = null;
}
}
// Recursive function to insert all nodes
// into a hash set.
function storeAllNodes(root, nodeSet) {
if (!root) return;
nodeSet.add(root.data);
storeAllNodes(root.left, nodeSet);
storeAllNodes(root.right, nodeSet);
}
// Recursive function to check if a leaf node
// is dead end or not.
function deadEndRecur(root, nodeSet) {
if (!root) return false;
// Check leaf node is dead end or not.
if (!root.left && !root.right) {
const val = root.data;
if (nodeSet.has(val - 1) && nodeSet.has(val + 1))
return true;
}
return deadEndRecur(root.left, nodeSet) ||
deadEndRecur(root.right, nodeSet);
}
function isDeadEnd(root) {
const nodeSet = new Set();
// to handle case when node value is 1
nodeSet.add(0);
storeAllNodes(root, nodeSet);
return deadEndRecur(root, nodeSet);
}
// Driver Code
const root = new Node(8);
root.left = new Node(5);
root.right = new Node(9);
root.left.left = new Node(2);
root.left.right = new Node(7);
root.left.left.left = new Node(1);
console.log(isDeadEnd(root));
Output
true
[Optimized Approach] Using Recursion and Range Values - O(n) time and O(h) space
The idea is to perform depth first search traversal on the tree, while maintaining the range of each subtree root. If for any leaf node, the size of range becomes 1 (this value is taken by leaf node already), it means no node can be inserted to this leaf node, and hence it is a dead end.
Step by step approach:
- Perform Depth first search on the root node and initialize the range as [1, Integer Maximum].
- For each node, If node is null, return false. If node is leaf node and the range of node is 1, return true as no other node can be inserted.
- Recur for left and right subtree.
// C++ program to Check whether BST contains Dead End or not
#include <bits/stdc++.h>
using namespace std;
class Node {
public:
int data;
Node *left, *right;
Node(int val){
data = val;
left = nullptr;
right = nullptr;
}
};
// Here mini and maxi defines the range of
// the subtree root. If the range consists
// only of 1 value (root value), it means
// no other value cannot be added to this.
bool dfs(Node* root, int mini, int maxi) {
// Base Case
if (root == nullptr) return false;
// If leaf node and no range left
if (root->left == nullptr && root->right == nullptr &&
mini == maxi) {
return true;
}
return dfs(root->left, mini, root->data-1) ||
dfs(root->right, root->data+1, maxi);
}
bool isDeadEnd(Node *root) {
return dfs(root, 1, INT_MAX);
}
int main() {
Node* root = new Node(8);
root->left = new Node(5);
root->right = new Node(9);
root->left->left = new Node(2);
root->left->right = new Node(7);
root->left->left->left = new Node(1);
if (isDeadEnd(root)) {
cout << "true" << endl;
} else {
cout << "false" << endl;
}
return 0;
}
// Java program to Check whether BST contains Dead End or not
class Node {
int data;
Node left, right;
Node(int val) {
data = val;
left = null;
right = null;
}
}
class GfG {
// Here mini and maxi defines the range of
// the subtree root. If the range consists
// only of 1 value (root value), it means
// no other value cannot be added to this.
static boolean dfs(Node root, int mini, int maxi) {
// Base Case
if (root == null) return false;
// If leaf node and no range left
if (root.left == null && root.right == null &&
mini == maxi) {
return true;
}
return dfs(root.left, mini, root.data-1) ||
dfs(root.right, root.data+1, maxi);
}
static boolean isDeadEnd(Node root) {
return dfs(root, 1, Integer.MAX_VALUE);
}
public static void main(String[] args) {
Node root = new Node(8);
root.left = new Node(5);
root.right = new Node(9);
root.left.left = new Node(2);
root.left.right = new Node(7);
root.left.left.left = new Node(1);
System.out.println(isDeadEnd(root));
}
}
# Python program to Check whether BST contains Dead End or not
class Node:
def __init__(self, val):
self.data = val
self.left = None
self.right = None
# Here mini and maxi defines the range of
# the subtree root. If the range consists
# only of 1 value (root value), it means
# no other value cannot be added to this.
def dfs(root, mini, maxi):
# Base Case
if root is None:
return False
# If leaf node and no range left
if root.left is None and root.right is None and mini == maxi:
return True
return dfs(root.left, mini, root.data-1) or dfs(root.right, root.data+1, maxi)
def isDeadEnd(root):
return dfs(root, 1, float('inf'))
if __name__ == "__main__":
root = Node(8)
root.left = Node(5)
root.right = Node(9)
root.left.left = Node(2)
root.left.right = Node(7)
root.left.left.left = Node(1)
if isDeadEnd(root):
print("true")
else:
print("false")
// C# program to Check whether BST contains Dead End or not
using System;
class Node {
public int data;
public Node left, right;
public Node(int val) {
data = val;
left = null;
right = null;
}
}
class GfG {
// Here mini and maxi defines the range of
// the subtree root. If the range consists
// only of 1 value (root value), it means
// no other value cannot be added to this.
static bool Dfs(Node root, int mini, int maxi) {
// Base Case
if (root == null) return false;
// If leaf node and no range left
if (root.left == null && root.right == null &&
mini == maxi) {
return true;
}
return Dfs(root.left, mini, root.data-1) ||
Dfs(root.right, root.data+1, maxi);
}
static bool IsDeadEnd(Node root) {
return Dfs(root, 1, int.MaxValue);
}
static void Main() {
Node root = new Node(8);
root.left = new Node(5);
root.right = new Node(9);
root.left.left = new Node(2);
root.left.right = new Node(7);
root.left.left.left = new Node(1);
if (IsDeadEnd(root)) {
Console.WriteLine("true");
} else {
Console.WriteLine("false");
}
}
}
// JavaScript program to Check whether BST contains Dead End or not
class Node {
constructor(val) {
this.data = val;
this.left = null;
this.right = null;
}
}
// Here mini and maxi defines the range of
// the subtree root. If the range consists
// only of 1 value (root value), it means
// no other value cannot be added to this.
function dfs(root, mini, maxi) {
// Base Case
if (root === null) return false;
// If leaf node and no range left
if (root.left === null && root.right === null &&
mini === maxi) {
return true;
}
return dfs(root.left, mini, root.data-1) ||
dfs(root.right, root.data+1, maxi);
}
function isDeadEnd(root) {
return dfs(root, 1, Number.MAX_SAFE_INTEGER);
}
// Driver Code
let root = new Node(8);
root.left = new Node(5);
root.right = new Node(9);
root.left.left = new Node(2);
root.left.right = new Node(7);
root.left.left.left = new Node(1);
console.log(isDeadEnd(root));
Output
true
Output:
Output: