Open In App

Check if a Binary Tree (not BST) has duplicate values

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Check if a Binary Tree (not BST) has duplicate values

To check if a binary tree has duplicate values, you can follow these steps:

  1. Create a set to store the values that have been encountered so far.
  2. Start a traversal of the binary tree. For each node, check if its value is in the set. If it is, return true to indicate that the tree contains duplicate values. If it is not, add the value to the set and continue the traversal.
  3. When the traversal is complete, return false to indicate that no duplicate values were found.

Examples: 

Input : Root of below tree
         1
       /   \
      2     3
             \
              2
Output : Yes
Explanation : The duplicate value is 2.

Input : Root of below tree
         1
       /   \
     20     3
             \
              4
Output : No
Explanation : There are no duplicates.

A simple solution is to store inorder traversal of given binary tree in an array. Then check if array has duplicates or not. We can avoid the use of array and solve the problem in O(n) time. The idea is to use hashing. We traverse the given tree, for every node, we check if it already exists in hash table. If exists, we return true (found duplicate). If it does not exist, we insert into hash table.

Implementation:

C++




// C++ Program to check duplicates
// in Binary Tree
#include <bits/stdc++.h>
using namespace std;
 
// A binary tree Node has data,
// pointer to left child
// and a pointer to right child
struct Node {
    int data;
    struct Node* left;
    struct Node* right;
};
 
// Helper function that allocates
// a new Node with the given data
// and NULL left and right pointers.
struct Node* newNode(int data)
{
    struct Node* node = new Node;
    node->data = data;
    node->left = node->right = NULL;
    return (node);
}
 
bool checkDupUtil(Node* root, unordered_set<int> &s)
{
    // If tree is empty, there are no
    // duplicates.
    if (root == NULL)
       return false;
 
    // If current node's data is already present.
    if (s.find(root->data) != s.end())
       return true;
 
    // Insert current node
    s.insert(root->data);
     
    // Recursively check in left and right
    // subtrees.
    return checkDupUtil(root->left, s) ||
           checkDupUtil(root->right, s);
}
 
// To check if tree has duplicates
bool checkDup(struct Node* root)
{
    unordered_set<int> s;
    return checkDupUtil(root, s);
}
 
// Driver program to test above functions
int main()
{
    struct Node* root = newNode(1);
    root->left = newNode(2);
    root->right = newNode(2);
    root->left->left = newNode(3);
    if (checkDup(root))
        printf("Yes");
    else
        printf("No");
 
    return 0;
}


Java




// Java Program to check duplicates
// in Binary Tree
import java.util.HashSet;
public class CheckDuplicateValues {
 
    //Function that used HashSet to find presence of duplicate nodes
    public static boolean checkDupUtil(Node root, HashSet<Integer> s)
    {
        // If tree is empty, there are no
        // duplicates. 
        if (root == null)
            return false;
   
        // If current node's data is already present.
        if (s.contains(root.data))
            return true;
   
        // Insert current node
        s.add(root.data);
       
        // Recursively check in left and right
        // subtrees.
        return checkDupUtil(root.left, s) || checkDupUtil(root.right, s);
    }
   
    // To check if tree has duplicates
    public static boolean checkDup(Node root)
    {
        HashSet<Integer> s=new HashSet<>();
        return checkDupUtil(root, s);
    }
 
    public static void main(String args[]) {
        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(2);
        root.left.left = new Node(3);
        if (checkDup(root))
            System.out.print("Yes");
        else
            System.out.print("No");
    }
}
 
// A binary tree Node has data,
// pointer to left child
// and a pointer to right child
class Node {
    int data;
    Node left,right;
    Node(int data)
    {
        this.data=data;
    }
};
//This code is contributed by Gaurav Tiwari


Python




""" Program to check duplicates
# in Binary Tree """
 
# Helper function that allocates a new
# node with the given data and None
# left and right pointers.                                
class newNode:
 
    # Construct to create a new node
    def __init__(self, key):
        self.data = key
        self.left = None
        self.right = None
 
def checkDupUtil( root, s) :
 
    # If tree is empty, there are no
    # duplicates.
    if (root == None) :
        return False
 
    # If current node's data is already present.
    if root.data in s:
        return True
 
    # Insert current node
    s.add(root.data)
     
    # Recursively check in left and right
    # subtrees.
    return checkDupUtil(root.left, s) or checkDupUtil(root.right, s)
 
 
# To check if tree has duplicates
def checkDup( root) :
 
    s=set()
    return checkDupUtil(root, s)
 
 
# Driver Code
if __name__ == '__main__':
    root = newNode(1)
    root.left = newNode(2)
    root.right = newNode(2)
    root.left.left = newNode(3)
    if (checkDup(root)):
        print("Yes")
    else:
        print("No")
 
# This code is contributed by
# Shubham Singh(SHUBHAMSINGH10)


C#




// C# Program to check duplicates
// in Binary Tree
using System;
using System.Collections;
using System.Collections.Generic;
 
class CheckDuplicateValues
{
 
    //Function that used HashSet to
    // find presence of duplicate nodes
    public static Boolean checkDupUtil(Node root, HashSet<int> s)
    {
        // If tree is empty, there are no
        // duplicates.
        if (root == null)
            return false;
     
        // If current node's data is already present.
        if (s.Contains(root.data))
            return true;
     
        // Insert current node
        s.Add(root.data);
         
        // Recursively check in left and right
        // subtrees.
        return checkDupUtil(root.left, s) ||
                checkDupUtil(root.right, s);
    }
     
    // To check if tree has duplicates
    public static Boolean checkDup(Node root)
    {
        HashSet<int> s = new HashSet<int>();
        return checkDupUtil(root, s);
    }
 
    public static void Main(String []args)
    {
        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(2);
        root.left.left = new Node(3);
        if (checkDup(root))
            Console.Write("Yes");
        else
            Console.Write("No");
    }
}
 
// A binary tree Node has data,
// pointer to left child
// and a pointer to right child
public class Node
{
    public int data;
    public Node left, right;
    public Node(int data)
    {
        this.data = data;
    }
};
 
// This code is contributed by Arnab Kundu


Javascript




<script>
 
    // JavaScript Program to check duplicates in Binary Tree
     
    class Node
    {
        constructor(data) {
           this.left = null;
           this.right = null;
           this.data = data;
        }
    }
 
    // Function that used HashSet to find
    // presence of duplicate nodes
    function checkDupUtil(root, s)
    {
        // If tree is empty, there are no
        // duplicates. 
        if (root == null)
            return false;
     
        // If current node's data is already present.
        if (s.has(root.data))
            return true;
     
        // Insert current node
        s.add(root.data);
         
        // Recursively check in left and right
        // subtrees.
        return checkDupUtil(root.left, s) ||
        checkDupUtil(root.right, s);
    }
     
    // To check if tree has duplicates
    function checkDup(root)
    {
        let s = new Set();
        return checkDupUtil(root, s);
    }
     
    let root = new Node(1);
    root.left = new Node(2);
    root.right = new Node(2);
    root.left.left = new Node(3);
    if (checkDup(root))
      document.write("Yes");
    else
      document.write("No");
     
</script>


Output

Yes

Time complexity: O(n), The time complexity of the above code is O(n) as we traverse the tree once and insert each node into the unordered set. 

Auxiliary Space: O(n),The space complexity of the above code is O(n) as we store all the nodes into the unordered set.

EXAMPLE 2 :

C++




#include <iostream>
#include <unordered_set>
 
using namespace std;
 
class Node {
public:
    int data;
    Node* left;
    Node* right;
 
    Node(int data)
    {
        this->data = data;
        this->left = NULL;
        this->right = NULL;
    }
};
 
class BinaryTree {
public:
    Node* root;
 
    bool hasDuplicateValues()
    {
        unordered_set<int> values;
        return hasDuplicateValues(root, values);
    }
 
private:
    bool hasDuplicateValues(Node* focusNode,
                            unordered_set<int>& values)
    {
        if (focusNode == NULL) {
            return false;
        }
 
        if (values.count(focusNode->data) > 0) {
            return true;
        }
 
        values.insert(focusNode->data);
        return hasDuplicateValues(focusNode->left, values)
               || hasDuplicateValues(focusNode->right,
                                     values);
    }
};
 
int main()
{
    BinaryTree tree;
 
    tree.root = new Node(1);
    tree.root->left = new Node(2);
    tree.root->right = new Node(2);
 
    cout << boolalpha << tree.hasDuplicateValues()
         << endl; // prints "true"
 
    tree.root->right = new Node(3);
 
    cout << boolalpha << tree.hasDuplicateValues()
         << endl; // prints "false"
 
    return 0;
}


Java




import java.util.HashSet;
 
class Node {
  int data;
  Node left;
  Node right;
 
  public Node(int data) {
    this.data = data;
  }
}
 
class BinaryTree {
  Node root;
 
  public boolean hasDuplicateValues() {
    HashSet<Integer> values = new HashSet<>();
    return hasDuplicateValues(root, values);
  }
 
  private boolean hasDuplicateValues(Node focusNode, HashSet<Integer> values) {
    if (focusNode == null) {
      return false;
    }
 
    if (values.contains(focusNode.data)) {
      return true;
    }
 
    values.add(focusNode.data);
    return hasDuplicateValues(focusNode.left, values) || hasDuplicateValues(focusNode.right, values);
  }
}
 
public class Main {
  public static void main(String[] args) {
    BinaryTree tree = new BinaryTree();
 
    tree.root = new Node(1);
    tree.root.left = new Node(2);
    tree.root.right = new Node(2);
 
    System.out.println(tree.hasDuplicateValues()); // prints "true"
 
    tree.root.right = new Node(3);
 
    System.out.println(tree.hasDuplicateValues()); // prints "false"
  }
}


Python3




# The following is the Python equivalent of the Java code above:
 
class Node:
  def __init__(self, data):
    self.data = data
    self.left = None
    self.right = None
 
class BinaryTree:
  def __init__(self):
    self.root = None
 
  def hasDuplicateValues(self):
    values = set()
    return self.hasDuplicateValuesRecursive(self.root, values)
 
  def hasDuplicateValuesRecursive(self, focusNode, values):
    if focusNode is None:
      return False
     
    if focusNode.data in values:
      return True
 
    values.add(focusNode.data)
    return self.hasDuplicateValuesRecursive(focusNode.left, values) or self.hasDuplicateValuesRecursive(focusNode.right, values)
 
def main():
  tree = BinaryTree()
 
  tree.root = Node(1)
  tree.root.left = Node(2)
  tree.root.right = Node(2)
 
  print(tree.hasDuplicateValues()) # prints "true"
 
  tree.root.right = Node(3)
 
  print(tree.hasDuplicateValues()) # prints "false"
 
if __name__ == '__main__':
  main()


C#




using System;
using System.Collections.Generic;
 
public class Node
{
    public int data; // holds the value of the node
    public Node left; // reference to the left child node
    public Node right; // reference to the right child node
 
    public Node(int data)
    {
        this.data = data; // sets the value of the node
    }
}
 
public class BinaryTree
{
    public Node root; // reference to the root node of the binary tree
 
    public bool HasDuplicateValues()
    {
        HashSet<int> values = new HashSet<int>(); // create a HashSet to store unique values encountered in the tree
        return HasDuplicateValues(root, values); // call the recursive function to check for duplicate values
    }
 
    private bool HasDuplicateValues(Node focusNode, HashSet<int> values)
    {
        if (focusNode == null)
        {
            return false; // base case: if the current node is null, return false (no duplicate values found)
        }
 
        if (values.Contains(focusNode.data))
        {
            return true; // if the current node's value has already been added to the HashSet, return true (duplicate value found)
        }
 
        values.Add(focusNode.data); // add the current node's value to the HashSet
 
        // recursively check for duplicate values in the left and right subtrees
        return HasDuplicateValues(focusNode.left, values) || HasDuplicateValues(focusNode.right, values);
    }
}
 
public class MainClass
{
    public static void Main(string[] args)
    {
        BinaryTree tree = new BinaryTree();
 
        // create a binary tree with duplicate values
        tree.root = new Node(1);
        tree.root.left = new Node(2);
        tree.root.right = new Node(2);
 
        Console.WriteLine(tree.HasDuplicateValues()); // prints "True" (duplicate value found)
 
        // modify the binary tree to remove duplicate values
        tree.root.right = new Node(3);
 
        Console.WriteLine(tree.HasDuplicateValues()); // prints "False" (no duplicate values found)
    }
}


Javascript




class Node {
  constructor(data) {
    this.data = data;
    this.left = null;
    this.right = null;
  }
}
 
class BinaryTree {
  constructor() {
    this.root = null;
  }
 
  hasDuplicateValues() {
    const values = new Set();
    return this._hasDuplicateValues(this.root, values);
  }
 
  _hasDuplicateValues(focusNode, values) {
    if (focusNode === null) {
      return false;
    }
 
    if (values.has(focusNode.data)) {
      return true;
    }
 
    values.add(focusNode.data);
    return (
      this._hasDuplicateValues(focusNode.left, values) ||
      this._hasDuplicateValues(focusNode.right, values)
    );
  }
}
 
const tree = new BinaryTree();
 
tree.root = new Node(1);
tree.root.left = new Node(2);
tree.root.right = new Node(2);
 
console.log(tree.hasDuplicateValues()); // prints "true"
 
tree.root.right = new Node(3);
 
console.log(tree.hasDuplicateValues()); // prints "false"


Output

true
false

Complexity analysis:

The hasDuplicateValues method has a time complexity of O(n), where n is the number of nodes in the binary tree. This is because the method visits each node exactly once in order to check if it has already been seen before.

The space complexity of the hasDuplicateValues method is O(m), where m is the number of unique values in the binary tree. The HashSet values stores all the unique values that have been seen so far, and its size can at most be equal to the number of unique values in the binary tree. This is because if there are no duplicates in the tree, the size of the HashSet will be equal to the number of nodes in the tree, which is n.
Otherwise, if there are duplicates, the size of the set will be less than the number of nodes, hence m<=n.

In the worst-case scenario, where all the values in the tree are different, the space complexity of the method would be O(n). In the best-case scenario, where all the values in the tree are the same, the space complexity of the method would be O(1).



Last Updated : 02 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads