Given N nodes numbered from 0 to n-1, also given the E number of directed edges, determine whether the given nodes all together form a single binary tree or not.
Examples:
Input: N = 4, edges[][] = [[0 1], [0 2], [2 3]]
Output: true
Explanation: Form a single binary tree with a unique root node.Input: N = 4, edges[][] = [[0 1], [0 2], [1 3], [2 3]]
Output: false
Explanation: Not form a single binary tree because they contain a cycle.
Approach: To solve the problem follow the below idea:
To determine if the given nodes form a single binary tree, you can use a Depth-First Search (DFS) algorithm to traverse the graph and check for the following conditions:
- The Graph should be connected
- There should be exactly one node with an in-degree of 0, which will be the root of the binary tree.
- Every other node should have an in-degree of 1 , except for the root node, which should have an in-degree of 0.
- Also for each node the number of childrens should be less than equal to 2.
Steps to Solve the problem:
- In a binary tree, every node (except the root) should have one parent.
- We can use an unordered_map called inDegree to store the in-degree of each node.
- If any node has an in-degree greater than 1, it means it has more than one parent, which violates the binary tree condition rule.
- Similarly, for each parent node, we need to count the number of children it has.
- If any node has more than two children, it also violates the binary tree condition. We use another unordered_map called childrenCount to keep track of this.
- A binary tree should have exactly one root node. We count the number of nodes with an in-degree of 0.
- If there is more than one such node, it means there is more than one root, which is not allowed in a binary tree.
Below is the implementation of the above idea:
// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
bool isBinaryTree(int N, vector<vector<int> >& edges)
{
if (N == 0) {
return false;
}
unordered_map<int, int> inDegree;
unordered_map<int, int> childrenCount;
for (vector<int>& edge : edges) {
int from = edge[0];
int to = edge[1];
inDegree[to]++;
childrenCount[from]++;
if (inDegree[to] > 1 || childrenCount[from] > 2) {
// More than two children or more
// than one parent, not a binary
// tree.
return false;
}
}
int rootCount = 0;
for (int i = 0; i < N; i++) {
if (inDegree[i] == 0) {
rootCount++;
if (rootCount > 1) {
// More than one root, not a
// binary tree.
return false;
}
}
}
return rootCount == 1;
}
// Drivers code
int main()
{
int N = 4;
vector<vector<int> > edges
= { { 0, 1 }, { 0, 2 }, { 0, 3 } };
// Function Call
if (isBinaryTree(N, edges))
cout << "true" << endl;
else
cout << "false" << endl;
return 0;
}
// Java code for the above approach:
import java.util.*;
class GFG {
static boolean isBinaryTree(int N, int[][] edges)
{
if (N == 0) {
return false;
}
Map<Integer, Integer> inDegree = new HashMap<>();
Map<Integer, Integer> childrenCount
= new HashMap<>();
for (int[] edge : edges) {
int from = edge[0];
int to = edge[1];
inDegree.put(to,
inDegree.getOrDefault(to, 0) + 1);
childrenCount.put(
from,
childrenCount.getOrDefault(from, 0) + 1);
if (inDegree.get(to) > 1
|| childrenCount.get(from) > 2) {
// More than two children or more
// than one parent, not a binary
// tree.
return false;
}
}
int rootCount = 0;
for (int i = 0; i < N; i++) {
if (inDegree.getOrDefault(i, 0) == 0) {
rootCount++;
if (rootCount > 1) {
// More than one root, not a
// binary tree.
return false;
}
}
}
return rootCount == 1;
}
// Drivers code
public static void main(String[] args)
{
int N = 4;
int[][] edges = { { 0, 1 }, { 0, 2 }, { 0, 3 } };
// Function Call
if (isBinaryTree(N, edges)) {
System.out.println("true");
}
else {
System.out.println("false");
}
}
}
// This code is contributed by ragul21
from collections import defaultdict
def is_binary_tree(N, edges):
if N == 0:
return False
in_degree = defaultdict(int)
children_count = defaultdict(int)
for edge in edges:
from_node, to_node = edge
in_degree[to_node] += 1
children_count[from_node] += 1
if in_degree[to_node] > 1 or children_count[from_node] > 2:
# More than two children or more than one parent, not a binary tree.
return False
root_count = 0
for i in range(N):
if in_degree[i] == 0:
root_count += 1
if root_count > 1:
# More than one root, not a binary tree.
return False
return root_count == 1
# Driver code
if __name__ == "__main__":
N = 4
edges = [[0, 1], [0, 2], [0, 3]]
# Function Call
if is_binary_tree(N, edges):
print("true")
else:
print("false")
# This code is contributed by shivamgupta0987654321
// C# Implementation
using System;
using System.Collections.Generic;
class Program
{
static bool IsBinaryTree(int N, int[][] edges)
{
if (N == 0)
{
return false;
}
Dictionary<int, int> inDegree = new Dictionary<int, int>();
Dictionary<int, int> childrenCount = new Dictionary<int, int>();
foreach (int[] edge in edges)
{
int from = edge[0];
int to = edge[1];
if (!inDegree.ContainsKey(to))
{
inDegree[to] = 0;
}
inDegree[to]++;
if (!childrenCount.ContainsKey(from))
{
childrenCount[from] = 0;
}
childrenCount[from]++;
if (inDegree[to] > 1 || childrenCount[from] > 2)
{
// More than two children or more than one parent, not a binary tree.
return false;
}
}
int rootCount = 0;
for (int i = 0; i < N; i++)
{
if (!inDegree.ContainsKey(i) || inDegree[i] == 0)
{
rootCount++;
if (rootCount > 1)
{
// More than one root, not a binary tree.
return false;
}
}
}
return rootCount == 1;
}
static void Main(string[] args)
{
int N = 4;
int[][] edges = { new int[] { 0, 1 }, new int[] { 0, 2 }, new int[] { 0, 3 } };
// Function Call
if (IsBinaryTree(N, edges))
{
Console.WriteLine("true");
}
else
{
Console.WriteLine("false");
}
}
}
// This code is contributed by Sakshi
function GFG(N, edges) {
if (N === 0) {
return false;
}
const inDegree = new Map();
const childrenCount = new Map();
for (const edge of edges) {
const from = edge[0];
const to = edge[1];
inDegree.set(to, (inDegree.get(to) || 0) + 1);
childrenCount.set(from, (childrenCount.get(from) || 0) + 1);
if (inDegree.get(to) > 1 || childrenCount.get(from) > 2) {
// More than two children or more than one parent
// not a binary tree.
return false;
}
}
let rootCount = 0;
for (let i = 0; i < N; i++) {
if (!inDegree.has(i)) {
rootCount++;
if (rootCount > 1) {
// More than one root, not a binary tree.
return false;
}
}
}
return rootCount === 1;
}
// Drivers code
const N = 4;
const edges = [
[0, 1],
[0, 2],
[0, 3]
];
// Function Call
if (GFG(N, edges)) {
console.log("true");
} else {
console.log("false");
}
Output
false
Time complexity: O(N + E), where N is the number of nodes and E is the number of edges.
Auxiliar Space: O(N + E), where N is the number of nodes and E is the number of edges.