Open In App

Check whether BST contains Dead End or not

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, we are not able to insert any element after that node.

Examples:  

Input :        8
/ \
5 9
/ \
2 7
/
1
Output : Yes
Explanation : Node "1" is the dead End because
after that we cant insert any element.

Input : 8
/ \
7 10
/ / \
2 9 13

Output : Yes
Explanation : We can't insert any element at
node 9.

If we take a closer look at the problem, we can notice that we basically need to check if there is a leaf node with value x such that x+1 and x-1 exist in BST with the exception of x = 1. For x = 1, we can't insert 0 as the problem statement says BST contains positive integers only.

To implement the above idea we first traverse the whole BST and store all nodes in a set. We also store all leaves in a separate hash to avoid re-traversal of BST. Finally, we check for every leaf node x, if x-1 and x+1 are present in set or not.

Below is a C++ implementation of the above idea. 

#include<bits/stdc++.h>
using namespace std;
// A BST node
struct Node
{
    int data;
    struct Node *left, *right;
};
// A utility function to create a new node
Node *newNode(int data)
{
    Node *temp = new Node;
    temp->data = data;
    temp->left = temp->right = NULL;
    return temp;
}
/* A utility function to insert a new Node
  with given key in BST */
struct Node* insert(struct Node* node, int key)
{
    /* If the tree is empty, return a new Node */
    if (node == NULL) return newNode(key);
    /* Otherwise, recur down the tree */
    if (key < node->data)
        node->left = insert(node->left, key);
    else if (key > node->data)
        node->right = insert(node->right, key);
    /* return the (unchanged) Node pointer */
    return node;
}
// Returns true if there is a dead end in tree,
// else false.
bool isDeadEndUtil(Node *root, int low, int high) {
    // Base case
    if (root == NULL)
        return false;
    // Check if current node falls within the range
    if (root->data >= low && root->data <= high)
        return true;
    // Recur for left and right subtrees
    return isDeadEndUtil(root->left, low, root->data - 1) || isDeadEndUtil(root->right, root->data + 1, high);
}
bool isDeadEnd(Node *root) {
    return isDeadEndUtil(root, 1, INT_MAX);
}
// Driver program
int main()
{
    Node *root = NULL;
    root = insert(root, 8);
    root = insert(root, 5);
    root = insert(root, 2);
    root = insert(root, 3);
    root = insert(root, 7);
    root = insert(root, 11);
    root = insert(root, 4);
    if (isDeadEnd(root) == true)
        cout << "Yes " << endl;
    else
        cout << "No " << endl;
    return 0;
}
// Java program check whether BST contains
// dead end or not
import java.util.*;

class Main {
    // create two empty hash sets that store all
    // BST elements and leaf nodes respectively.
    static HashSet<Integer> all_nodes
        = new HashSet<Integer>();
    static HashSet<Integer> leaf_nodes
        = new HashSet<Integer>();

    /* A utility function to insert a new Node
    with given key in BST */
    public static Node insert(Node node, int key)
    {
        /* If the tree is empty, return a new Node */
        if (node == null)
            return new Node(key);

        /* Otherwise, recur down the tree */
        if (key < node.data)
            node.left = insert(node.left, key);
        else if (key > node.data)
            node.right = insert(node.right, key);

        /* return the Node */
        return node;
    }
    // Function to store all node of given binary search
    // tree
    public static void storeNodes(Node root)
    {
        if (root == null)
            return;

        // store all node of binary search tree
        all_nodes.add(root.data);

        // store leaf node in leaf_hash
        if (root.left == null && root.right == null) {
            leaf_nodes.add(root.data);
            return;
        }

        // recur call rest tree
        storeNodes(root.left);
        storeNodes(root.right);
    }

    // Returns true if there is a dead end in tree,
    // else false.
    public static boolean isDeadEnd(Node root)
    {
        // Base case
        if (root == null)
            return false;

        // insert 0 in 'all_nodes' for handle case
        // if bst contain value 1
        all_nodes.add(0);

        // Call storeNodes function to store all BST Node
        storeNodes(root);

        // Traversal leaf node and check Tree contain
        // continuous sequence of
        // size tree or Not
        for (int i : leaf_nodes) {
            int x = i;

            // Here we check first and last element of
            // continuous sequence that are x-1 & x+1
            if (all_nodes.contains(x + 1)
                && all_nodes.contains(x - 1)) {
                return true;
            }
        }
        return false;
    }

    // Driver program
    public static void main(String[] args)
    {
        /*       8
               /   \
              5    11
             /  \
            2    7
             \
              3
               \
                4 */
        Node root = null;
        root = insert(root, 8);
        root = insert(root, 5);
        root = insert(root, 2);
        root = insert(root, 3);
        root = insert(root, 7);
        root = insert(root, 11);
        root = insert(root, 4);
        if (isDeadEnd(root) == true)
            System.out.println("Yes");

        else
            System.out.println("No");
    }
}

// A BST node
class Node {
    int data;
    Node left, right;

    Node(int data)
    {
        this.data = data;
        left = null;
        right = null;
    }
}

// This code is contributed by Tapesh(tapeshdua420)
# Python 3 program check
# whether BST contains
# dead end or not
all_nodes = set()
leaf_nodes = set()

# A BST node
class newNode:

    def __init__(self, data):

        self.data = data
        self.left = None
        self.right = None


''' A utility function to 
    insert a new Node with 
    given key in BST '''
def insert(node, key):
    '''/* If the tree is empty, 
          return a new Node */ '''
    if (node == None):
        return newNode(key)

    # Otherwise, recur down
    # the tree
    if (key < node.data):
        node.left = insert(node.left,
                           key)
    elif (key > node.data):
        node.right = insert(node.right,
                            key)

    # return the (unchanged)
    # Node pointer
    return node

# Function to store all node
# of given binary search tree
def storeNodes(root):

    global all_nodes
    global leaf_nodes
    if (root == None):
        return

    # store all node of binary
    # search tree
    all_nodes.add(root.data)

    # store leaf node in leaf_hash
    if (root.left == None and
            root.right == None):
        leaf_nodes.add(root.data)
        return

    # recur call rest tree
    storeNodes(root. left)
    storeNodes(root.right)

# Returns true if there is
# a dead end in tree,
# else false.
def isDeadEnd(root):

    global all_nodes
    global leaf_nodes

    # Base case
    if (root == None):
        return False

    # create two empty hash
    # sets that store all BST
    # elements and leaf nodes
    # respectively.

    # insert 0 in 'all_nodes'
    # for handle case if bst
    # contain value 1
    all_nodes.add(0)

    # Call storeNodes function
    # to store all BST Node
    storeNodes(root)

    # Traversal leaf node and
    # check Tree contain
    # continuous sequence of
    # size tree or Not
    for x in leaf_nodes:

        # Here we check first and
        # last element of continuous
        # sequence that are x-1 & x+1
        if ((x + 1) in all_nodes and
                (x - 1) in all_nodes):
            return True

    return False


# Driver code
if __name__ == '__main__':

    '''/*       8
       /   \
      5    11
     /  \
    2    7
     \
      3
       \
        4 */
    '''
    root = None
    root = insert(root, 8)
    root = insert(root, 5)
    root = insert(root, 2)
    root = insert(root, 3)
    root = insert(root, 7)
    root = insert(root, 11)
    root = insert(root, 4)

    if(isDeadEnd(root) == True):
        print("Yes")
    else:
        print("No")

# This code is contributed by bgangwar59
// C# code for the above approach
using System;
using System.Collections.Generic;

// A BST node
public class Node {
  public int data;
  public Node left, right;

  public Node(int data)
  {
    this.data = data;
    left = null;
    right = null;
  }
}

public class GFG {

  // create two empty hash sets that store all
  // BST elements and leaf nodes respectively.
  static HashSet<int> all_nodes = new HashSet<int>();
  static HashSet<int> leaf_nodes = new HashSet<int>();

  /* A utility function to insert a new Node
with given key in BST */
  public static Node insert(Node node, int key)
  {
    /* If the tree is empty, return a new Node */
    if (node == null)
      return new Node(key);

    /* Otherwise, recur down the tree */
    if (key < node.data)
      node.left = insert(node.left, key);
    else if (key > node.data)
      node.right = insert(node.right, key);

    /* return the Node */
    return node;
  }

  // Function to store all node of given binary search
  // tree
  public static void storeNodes(Node root)
  {
    if (root == null)
      return;

    // store all node of binary search tree
    all_nodes.Add(root.data);

    // store leaf node in leaf_hash
    if (root.left == null && root.right == null) {
      leaf_nodes.Add(root.data);
      return;
    }

    // recur call rest tree
    storeNodes(root.left);
    storeNodes(root.right);
  }

  // Returns true if there is a dead end in tree,
  // else false.
  public static bool isDeadEnd(Node root)
  {
    // Base case
    if (root == null)
      return false;

    // insert 0 in 'all_nodes' for handle case
    // if bst contain value 1
    all_nodes.Add(0);

    // Call storeNodes function to store all BST Node
    storeNodes(root);

    // Traversal leaf node and check Tree contain
    // continuous sequence of
    // size tree or Not
    foreach(int i in leaf_nodes)
    {
      int x = i;

      // Here we check first and last element of
      // continuous sequence that are x-1 & x+1
      if (all_nodes.Contains(x + 1)
          && all_nodes.Contains(x - 1)) {
        return true;
      }
    }
    return false;
  }

  static public void Main()
  {

    // Code
    /*       8
               /   \
              5    11
             /  \
            2    7
             \
              3
               \
                4 */
    Node root = null;
    root = insert(root, 8);
    root = insert(root, 5);
    root = insert(root, 2);
    root = insert(root, 3);
    root = insert(root, 7);
    root = insert(root, 11);
    root = insert(root, 4);
    if (isDeadEnd(root) == true)
      Console.WriteLine("Yes");

    else
      Console.WriteLine("No");
  }
}

// This code is contributed by lokesh.
class Node {
    constructor(data) {
        this.data = data;
        this.left = null;
        this.right = null;
    }
}

// A utility function to create a new node
function newNode(data) {
    let temp = new Node(data);
    return temp;
}

/* A utility function to insert a new Node
  with given key in BST */
function insert(node, key) {
    /* If the tree is empty, return a new Node */
    if (node == null) return newNode(key);

    /* Otherwise, recur down the tree */
    if (key < node.data) {
        node.left = insert(node.left, key);
    } else if (key > node.data) {
        node.right = insert(node.right, key);
    }

    /* return the (unchanged) Node pointer */
    return node;
}

// Function to store all node of given binary search tree
function storeNodes(root, all_nodes, leaf_nodes) {
    if (root == null) return;

    // store all node of binary search tree
    all_nodes.add(root.data);

    // store leaf node in leaf_nodes
    if (root.left == null && root.right == null) {
        leaf_nodes.add(root.data);
        return;
    }

    // recur call rest tree
    storeNodes(root.left, all_nodes, leaf_nodes);
    storeNodes(root.right, all_nodes, leaf_nodes);
}

// Returns true if there is a dead end in tree,
// else false.
function isDeadEnd(root) {
    // Base case
    if (root == null) return false;

    // create two empty sets that store all
    // BST elements and leaf nodes respectively.
    let all_nodes = new Set();
    let leaf_nodes = new Set();

    // insert 0 in 'all_nodes' for handle case
    // if bst contain value 1
    all_nodes.add(0);

    // Call storeNodes function to store all BST Node
    storeNodes(root, all_nodes, leaf_nodes);

    // Traversal leaf node and check Tree contain
    // continuous sequence of
    // size tree or Not
    for (let i of leaf_nodes) {
        let x = i;

        // Here we check first and last element of
        // continuous sequence that are x-1 & x+1
        if (all_nodes.has(x + 1) && all_nodes.has(x - 1)) return true;
    }

    return false;
}

// Driver program

    /*       8
            /   \
           5    11
          /  \
         2    7
          \
           3
            \
             4 */
    let root = null;
    root = insert(root, 8);
    root = insert(root, 5);
    root = insert(root, 2);
    root = insert(root, 3);
    root = insert(root, 7);
    root = insert(root, 11);
    root = insert(root, 4);
if (isDeadEnd(root) == true) {
console.log("Yes");
} else {
console.log("No");
}

// This code is contributed by lokeshpotta20.

Output
Yes 

Time Complexity : O(n)

The time complexity of the above algorithm is O(n) as we are traversing the entire tree to check for the dead end.

Space complexity: O(n)

The space complexity of the above algorithm is O(n) as we need to store all the elements in the unordered_set which is of size n.

Improved Approach

In the above approach we are using 2 hashmaps , one for storing all nodes and one for storing leaf nodes , instead of using 2 maps we can do this problem with 1 hashmap also .

We can pass the hashmap of all nodes and check if for node x there exists a x-1 and x+1 or not. If we got a node for which x+1 and x-1 both are present we will return true otherwise we will return false

Implementation:

// C++ program check whether BST contains
// dead end or not
#include<bits/stdc++.h>
using namespace std;

// A BST node
struct Node
{
    int data;
    struct Node *left, *right;
};

// A utility function to create a new node
Node *newNode(int data)
{
    Node *temp = new Node;
    temp->data = data;
    temp->left = temp->right = NULL;
    return temp;
}

/* A utility function to insert a new Node
  with given key in BST */
struct Node* insert(struct Node* node, int key)
{
    /* If the tree is empty, return a new Node */
    if (node == NULL) return newNode(key);

    /* Otherwise, recur down the tree */
    if (key < node->data)
        node->left = insert(node->left, key);
    else if (key > node->data)
        node->right = insert(node->right, key);

    /* return the (unchanged) Node pointer */
    return node;
}
void findallNodes(Node* root,map<int,int> &allnodes)
{
    if(root == NULL)
    return ;
    
    allnodes[root->data] = 1;
    findallNodes(root->left,allnodes);
    findallNodes(root->right,allnodes);
}
bool check(Node* root,map<int,int> &allnodes)
{
    if(root == NULL)
    return false;
    
    if(root->left == NULL and root->right == NULL)
    {
        int pre = root->data - 1;
        int next = root->data + 1;

        if(allnodes.find(pre) != allnodes.end() and allnodes.find(next) != allnodes.end())
        return true;
    }
    
    return check(root->left,allnodes) or check(root->right,allnodes);
    
}
bool isDeadEnd(Node *root)
{
    // Base case
   if (root == NULL)
        return false ;
    map<int,int> allnodes;
      // adding 0 for handling the exception of node having data = 1
    allnodes[0] = 1;
    findallNodes(root,allnodes);
    
    return check(root,allnodes);
    
}

// Driver program
int main()
{
/*       8
       /   \
      5    11
     /  \
    2    7
     \
      3
       \
        4 */
    Node *root = NULL;
    root = insert(root, 8);
    root = insert(root, 5);
    root = insert(root, 2);
    root = insert(root, 3);
    root = insert(root, 7);
    root = insert(root, 11);
    root = insert(root, 4);
    if (isDeadEnd(root) == true)
        cout << "Yes " << endl;
    else
        cout << "No " << endl;
    return 0;
}
// Java program check whether BST contains dead end or not
import java.io.*;
import java.util.*;

// A BST node
class Node {
  int data;
  Node left, right;

  Node(int data)
  {
    this.data = data;
    left = right = null;
  }
}

class GFG {

  Node root;

  void BST() { root = null; }

  // A utility function to insert a new Node with given
  // key in BST
  Node insert(Node node, int key)
  {
    // If the tree is empty, return a new node
    if (node == null) {
      return new Node(key);
    }

    // Otherwise, recur down the tree
    if (key < node.data) {
      node.left = insert(node.left, key);
    }
    else if (key > node.data) {
      node.right = insert(node.right, key);
    }

    // return the (unchanged) Node pointer
    return node;
  }

  void findAllNodes(Node root,
                    Map<Integer, Integer> allNodes)
  {
    if (root == null) {
      return;
    }

    allNodes.put(root.data, 1);
    findAllNodes(root.left, allNodes);
    findAllNodes(root.right, allNodes);
  }

  boolean check(Node root, Map<Integer, Integer> allNodes)
  {
    if (root == null) {
      return false;
    }

    if (root.left == null && root.right == null) {
      int pre = root.data - 1;
      int next = root.data + 1;

      if (allNodes.containsKey(pre)
          && allNodes.containsKey(next)) {
        return true;
      }
    }

    return check(root.left, allNodes)
      || check(root.right, allNodes);
  }

  boolean isDeadEnd(Node root)
  {
    // Base case
    if (root == null) {
      return false;
    }

    Map<Integer, Integer> allNodes
      = new HashMap<Integer, Integer>();
    // adding 0 for handling the exception of node
    // having date = 1
    allNodes.put(0, 1);
    findAllNodes(root, allNodes);

    return check(root, allNodes);
  }

  public static void main(String[] args)
  {
    /*
                 8
               /   \
              5    11
             /  \
            2    7
             \
              3
               \
                4     */
    GFG tree = new GFG();
    Node root = null;
    root = tree.insert(root, 8);
    root = tree.insert(root, 5);
    root = tree.insert(root, 2);
    root = tree.insert(root, 3);
    root = tree.insert(root, 7);
    root = tree.insert(root, 11);
    root = tree.insert(root, 4);

    if (tree.isDeadEnd(root) == true) {
      System.out.println("Yes");
    }
    else {
      System.out.println("No");
    }
  }
}

// This code is contributed by lokeshmvs21.
# Python program check whether BST contains
# dead end or not
# A BST node
class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None


# a utility function to create a new node
def newNode(data):
    return Node(data)
    
# a utility function to insert a new node
# with given key in BST
def insert(node, key):
    # if the tree is empty, return a new node
    if(node is None):
        return newNode(key)    
    
    # otherwise , recur down the tree
    if(key < node.data):
        node.left = insert(node.left, key)
    elif(key > node.data):
        node.right = insert(node.right, key)
    
    # return the (unchanged) Node pointer
    return node
    

allnodes = {}

def findallNodes(root):
    if(root is None):
        return
    
    allnodes[root.data] = 1
    findallNodes(root.left)
    findallNodes(root.right)


def check(root):
    if(root is None):
        return False
    
    if(root.left is None and root.right is None):
        pre = root.data - 1
        next = root.data + 1
        
        if(allnodes.get(pre) is not None and allnodes.get(next) is not None):
            return True
    
    return check(root.left) or check(root.right)


def isDeadEnd(root):
    if(root is None): 
        return False
    allnodes[0] = 1
    findallNodes(root)
    return check(root)


# driver program
root = None
root = insert(root, 8)
root = insert(root, 5)
root = insert(root, 2)
root = insert(root, 3)
root = insert(root, 7)
root = insert(root, 11)
root = insert(root, 4)

if(isDeadEnd(root) is True):
    print("Yes")
else:
    print("No")
    
# THIS CODE IS CONTRIBUTED BY KIRTI AGARWAL(KIRTIAGARWAL23121999)
    
// C# program check whether BST contains
// dead end or not

using System;
using System.Linq;
using System.Collections.Generic;

class GFG 
{

    // Structure of a Query
    class Node {
        public int data;
        public Node left, right;
        public Node(int data)
        {
            this.data=data;
            this.left=left;
            this.right=right;
        }
    }
    
    /* A utility function to insert a new Node
      with given key in BST */
    static Node insert(Node node, int  key)
    {
        /* If the tree is empty, return a new Node */
        if (node == null) 
            return new Node(key);
    
        /* Otherwise, recur down the tree */
        if (key < node.data)
            node.left = insert(node.left, key);
        else if (key > node.data)
            node.right = insert(node.right, key);
    
        /* return the (unchanged) Node pointer */
        return node;
    }
    static void findallNodes(Node root,Dictionary<int,int> allnodes)
    {
        if(root == null)
        return ;
        
        allnodes.Add(root.data, 1);
        findallNodes(root.left,allnodes);
        findallNodes(root.right,allnodes);
    }
    static bool check(Node root,Dictionary<int,int> allnodes)
    {
        if(root == null)
        return false;
        
        if(root.left == null && root.right == null)
        {
            int pre = root.data - 1;
            int next = root.data + 1;
    
            if(allnodes.ContainsKey(pre) ==true && allnodes.ContainsKey(next) ==true)
            return true;
        }
        
        return check(root.left,allnodes) || check(root.right,allnodes);
        
    }
    static bool isDeadEnd(Node root)
    {
        // Base case
       if (root == null)
            return false ;
        Dictionary<int,int> allnodes=new Dictionary<int, int>();
          // adding 0 for handling the exception of node having data = 1
        allnodes.Add(0,1);
        findallNodes(root,allnodes);
        
        return check(root,allnodes);
        
    }
    
    // Driver program
    static public void Main()
    {
    /*       8
           /   \
          5    11
         /  \
        2    7
         \
          3
           \
            4 */
        Node root = null;
        root = insert(root, 8);
        root = insert(root, 5);
        root = insert(root, 2);
        root = insert(root, 3);
        root = insert(root, 7);
        root = insert(root, 11);
        root = insert(root, 4);
        if (isDeadEnd(root) == true)
            Console.Write("Yes ");
        else
            Console.Write("No ");
    }
}
// JavaScript program to check whether BST contains
// dead end or not

class Node{
    constructor(data){
        this.data = data;
        this.left = null;
        this.right = null;
    }
}

// A utility function to create a new node
function newNode(data){
    let temp = new Node(data);
    return temp;
}

// A utility functiion to insert a new node
// with given key in BST
function insert(node, key){
    // If the tree is empty, return a new node
    if(node == null) return newNode(key);
    
    // Otherwise, recur down the tree
    if(key < node.data)
        node.left = insert(node.left, key);
    else if(key > node.data)
        node.right = insert(node.right, key);
    
    // return the (unchanged) Node pointer
    return node;
}

let allnodes = new Map();

function findallNodes(root){
    if(root == null) return;
    
    allnodes.set(root.data, 1);
    findallNodes(root.left);
    findallNodes(root.right);
}

function check(root){
    if(root == null) return false;
    
    if(root.left == null && root.right == null){
        let pre = root.data - 1;
        let next = root.data + 1;
        
        if(allnodes.has(pre) != false && allnodes.has(next) != false){
            return true;
        }
    }
    return check(root.left) || check(root.right);
}

function isDeadEnd(root){
    // Base Case
    if(root == null)
        return false;
    
    allnodes.set(0,1);
    findallNodes(root);
    return check(root);
}

// Driver Program
/*       8
       /   \
      5    11
     /  \
    2    7
     \
      3
       \
        4 
*/
let root = null;
root = insert(root, 8);
root = insert(root, 5);
root = insert(root, 2);
root = insert(root, 3);
root = insert(root, 7);
root = insert(root, 11);
root = insert(root, 4);

if(isDeadEnd(root) == true){
    console.log("Yes");   
}else{
    console.log("No");
}

// This code is contributed by Yash Agarwal(yashagarwal2852002)

Output
Yes 

Time Complexity: O(N) where N is the Number of nodes in a given binary tree.
Auxiliary Space: O(N)

Simple Recursive solution to check whether BST contains dead End
 

Article Tags :