Open In App

Number of connected components in a doubly linked list

Improve
Improve
Like Article
Like
Save
Share
Report

Given a doubly linked list ‘L’ and an array ‘refArr’ of references to the nodes of the doubly linked list ‘L’. Array ‘refArr’ does not contain any duplicate references and the references are not ORDERED
m <= total no. of nodes in the doubly linked list where m = size of the reference array. 
The task is to find the total number of connected components in the linked list ‘L’. 

A ‘connected component’ in linked list ‘L’ is defined as a group of nodes in the list with their references stored in the array ‘refArr’ and are adjacent to each other in the list.

Examples: 

Input: L = 5 <-> 2 <-> 10 <-> 1 <-> 3, refArr[] = {5, 10, 3, 1} 
Output:
Two connected components are 5 and 10 <-> 1 <-> 3. 
Since 2 is not included in the reference array, that makes 5 disconnected from the rest of the elements.

Input: L = 1 <-> 7 <-> 10 <-> 5 <-> 4 <-> 2, refArr[] = {5, 2, 7, 1} 
Output: Total number of connected components are 3 

Explanation:  

Let us take a double linked list ‘L’ as { N1 N2 N3 N4 N5 N6 } 
and the array ‘refArr’ as [ref_to_nodeN1, ref_to_nodeN4, ref_to_nodeN6, ref_to_nodeN2].

Output : 
This set of array ‘refArr’ and linked list ‘L’ contains 3 connected components, which are { [N1, N2], [N4], [N6] } . 
It is because references of the nodes N1 and N2 are present in the array ‘refArr’ and they are adjacent to each other in the list ‘L’ whereas N4 and N6 are not adjacent to N1, N2 or to each other. Hence, they form separate components.
Now, let the array ‘refArr’ be modified as [ref_to_nodeN4, ref_to_nodeN6, ref_to_nodeN5].

Output : 
This set of array ‘refArr’ and linked list ‘L’ contains 1 connected component, which is { [N4, N5, N6] } . 
It is because references of the nodes N4, N5 and N6 are present in the array ‘refArr’ and they are adjacent to each other in the list ‘L’. So, we together form 1 connected component.

Naive Approach: It involves traversing the array ‘refArr’ for each node of the linked list ’L’ and checking whether that element is present in the array or not. Also, maintain a Boolean variable which keeps track of whether the previous node in the linked list is in the array or not. Take a variable ‘cc’ which is initialized to 0 and indicates the no. of connected components in the linked list.

 Now, let us consider the multiple cases which occur while traversing: 

  • Case 1: If the previous node is in the array and the current node being traversed is also in the array then, the Boolean variable will remain 1 meaning that current node is in array but do not increment the variable ’cc’ since the current node forms a part of component already existing for the previous node.
  • Case 2: If the previous node is not in the array and the current node being traversed is in the array then, update the Boolean variable to mark ‘1’ meaning that current node is in the array and also increment the variable ’cc’ by 1 because the current node forms a new component.
  • Case 3: If the previous node is in the array and the current node being traversed is not in the array then, update the Boolean variable to mark 0 meaning that the current node is not in the array and do not increment the variable ’cc’ since the current node is not a part of any component.
  • Case 4: If the previous node is not in the array and the current node being traversed is also not in the array then, the Boolean variable will remain 0 meaning that current node is not in array and do not increment the variable ’cc’ since the current node is not a part of any component.

Now, after performing one of the 4 cases, move to the next node in the linked list and do the same for that node as well.

Time Complexity: O(n*m), where n = size of the linked list ‘L’ And, m = size of the reference array ‘refArr’. 
Space Complexity: O(1) 

Better Approach: This approach involves the use of unordered_set. Take a variable ‘connectedComponents’ which is initialized to 0. connectedComponents indicates the number of connected components in the linked list. 

Now for each element in reference array ‘refArr’: 

  • Add reference stored in the array to an unordered_set ‘refSet’.
  • If both previous and next siblings are present, then decrement the variable ‘connectedComponents’ by 1 which means that we have closed a gap between two components, so we must decrement the incorrectly counted components.
  • If only one of the previous and next siblings is present in the set, then no updating is done to the no. of components.
  • If none of the previous and next siblings is present in the set, then we must increment the incorrectly counted components because now, the current node forms a new component.

Below is the implementation of the above approach: 

C++




// A C++ program to find number
// of Connected Components in a doubly linked list.
#include <bits/stdc++.h>
using namespace std;
 
// Node of the doubly linked list
struct Node {
    int data;
    struct Node* next;
    struct Node* prev;
};
 
// Function to find number of connected
// components using a doubly linked list
// and a reference array
int func_connComp(struct Node** head_ref,
                  vector<struct Node*> refArr, int n)
{
    // Base case when the doubly
    // linked list is empty
    if (head_ref == NULL) {
        return 0;
    }
 
    // Initialise connectedComponents to zero
    int connectedComponents = 0;
 
    // Initialise an unordered set
    unordered_set<struct Node*> refSet;
 
    // Push the first element of the
    // refArr in the refSet and
    // set the connectedComponents to 1
    refSet.insert(refArr[0]);
    connectedComponents++;
 
    // Loop over all the elements of the refArr
    for (int i = 1; i < n; i++) {
 
        // insert each reference node to the refSet
        refSet.insert(refArr[i]);
 
        // If the reference node is the head of the linked list
        if (refArr[i]->prev == NULL) {
 
            // when next sibling of the head node is
            // not in the refSet
            if (refSet.find(refArr[i]->next) == refSet.end()) {
                connectedComponents++;
            }
        }
 
        // If the reference node is the
        // last node of the linked list*/
        else if (refArr[i]->next == NULL) {
 
            // when previous sibling of the
            // node is not in the refSet
            if (refSet.find(refArr[i]->next) == refSet.end()) {
                connectedComponents++;
            }
        }
 
        // the case when both previous and
        // next siblings of the current node
        // are in the refSet
        else if (refSet.find(refArr[i]->prev) != refSet.end()
                 && refSet.find(refArr[i]->next) != refSet.end()) {
            connectedComponents--;
        }
 
        /*the case when previous and next
        // siblings of the current node
        // are not in the refSet*/
        else if (refSet.find(refArr[i]->prev) == refSet.end()
                 && refSet.find(refArr[i]->next) == refSet.end()) {
            connectedComponents++;
        }
    }
    return connectedComponents;
}
 
// Function to insert a node at the
// beginning of the Doubly Linked List
Node* push(struct Node** head_ref, int new_data)
{
    /* allocate node */
    struct Node* new_node = new Node;
 
    struct Node* current_node = new_node;
    /* put in the data */
    new_node->data = new_data;
 
    /* since we are adding at the beginning,
    prev is always NULL */
    new_node->prev = NULL;
 
    /* link the old list of the new node */
    new_node->next = (*head_ref);
 
    /* change prev of head node to new node */
    if ((*head_ref) != NULL)
        (*head_ref)->prev = new_node;
 
    /* move the head to point to the new node */
    (*head_ref) = new_node;
 
    return current_node;
}
 
// Function to print nodes in a given
// doubly linked list
void printList(struct Node* node)
{
    while (node != NULL) {
        printf("%d ", node->data);
        node = node->next;
    }
}
 
// Driver code
int main()
{
 
    // Start with the empty list
    struct Node* head = NULL;
 
    // Let us create a linked list to test
    // the functions so as to find number
    // of Connected Components Created a
    // doubly linked list: 1 <-> 7 <-> 10 <-> 5 <-> 4 <-> 2
    struct Node* ref_to_nodeN2 = push(&head, 2);
    struct Node* ref_to_nodeN4 = push(&head, 4);
    struct Node* ref_to_nodeN5 = push(&head, 5);
    struct Node* ref_to_nodeN10 = push(&head, 10);
    struct Node* ref_to_nodeN7 = push(&head, 7);
    struct Node* ref_to_nodeN1 = push(&head, 1);
 
    vector<struct Node*> refArr{ ref_to_nodeN5,
                                         ref_to_nodeN2, ref_to_nodeN7, ref_to_nodeN1 };
 
    // This function will return the number
    // of connected components of doubly linked list
    int connectedComponents = func_connComp(&head, refArr, 4);
 
    cout << "Total number of connected components are "
         << connectedComponents << endl;
 
    return 0;
}


Java




// Java program to find number
// of Connected Components in a doubly linked list.
import java.util.HashSet;
 
public class GFG
{
   
  // Node of the doubly linked list
  static class Node {
    int data;
    Node next;
    Node prev;
  }
 
  // Function to find number of connected
  // components using a doubly linked list
  // and a reference array
  static int func_connComp(Node head_ref, Node[] refArr,
                           int n)
  {
    // Base case when the doubly
    // linked list is empty
    if (head_ref == null) {
      return 0;
    }
 
    // Initialise connectedComponents to zero
    int connectedComponents = 0;
 
    // Initialise an unordered set
    HashSet<Node> refSet = new HashSet<Node>();
 
    // Push the first element of the
    // refArr in the refSet and
    // set the connectedComponents to 1
    refSet.add(refArr[0]);
    connectedComponents++;
 
    // Loop over all the elements of the refArr
    for (int i = 1; i < n; i++) {
 
      // insert each reference node to the refSet
      refSet.add(refArr[i]);
 
      // If the reference node is the head of the
      // linked list
      if (refArr[i].prev == null) {
 
        // when next sibling of the head node is
        // not in the refSet
        if (refSet.contains(refArr[i].next)) {
          connectedComponents++;
        }
      }
 
      // If the reference node is the
      // last node of the linked list*/
      else if (refArr[i].next == null) {
 
        // when previous sibling of the
        // node is not in the refSet
        if (refSet.contains(refArr[i].next)) {
          connectedComponents++;
        }
      }
 
      // the case when both previous and
      // next siblings of the current node
      // are in the refSet
      else if (refSet.contains(refArr[i].prev)
               && refSet.contains(refArr[i].next)) {
        connectedComponents--;
      }
 
      /*the case when previous and next
            // siblings of the current node
            // are not in the refSet*/
      else if (!refSet.contains(refArr[i].prev)
               && !refSet.contains(refArr[i].next)) {
        connectedComponents++;
      }
    }
    return connectedComponents;
  }
 
  // Function to insert a node at the
  // beginning of the Doubly Linked List
  static Node push(int new_data)
  {
    /* allocate node */
    Node new_node = new Node();
 
    Node current_node = new_node;
    /* put in the data */
    new_node.data = new_data;
 
    /* since we are adding at the beginning,
        prev is always null */
    new_node.prev = null;
 
    /* link the old list of the new node */
    new_node.next = head;
 
    /* change prev of head node to new node */
    if ((head) != null)
      head.prev = new_node;
 
    /* move the head to point to the new node */
    head = new_node;
 
    return current_node;
  }
 
  // Function to print nodes in a given
  // doubly linked list
  static void printList(Node node)
  {
    while (node != null) {
      System.out.print(node.data + " ");
      node = node.next;
    }
  }
 
  // Start with the empty list
  static Node head = null;
 
  // Driver code
  public static void main(String[] args)
  {
 
    // Let us create a linked list to test
    // the functions so as to find number
    // of Connected Components Created a
    // doubly linked list: 1 <. 7 <. 10 <. 5 <. 4 <. 2
    Node ref_to_nodeN2 = push(2);
    Node ref_to_nodeN4 = push(4);
    Node ref_to_nodeN5 = push(5);
    Node ref_to_nodeN10 = push(10);
    Node ref_to_nodeN7 = push(7);
    Node ref_to_nodeN1 = push(1);
 
    Node[] refArr = { ref_to_nodeN5, ref_to_nodeN2,
                     ref_to_nodeN7, ref_to_nodeN1 };
 
    // This function will return the number
    // of connected components of doubly linked list
    int connectedComponents
      = func_connComp(head, refArr, 4);
 
    System.out.println(
      "Total number of connected components are "
      + connectedComponents);
  }
}
 
// This code is contributed by Lovely Jain


Python3




# A Python3 program to find number
# of Connected Components in a doubly linked list.
  
# Node of the doubly linked list
class Node:  
    def __init__(self):      
        self.data = 0
        self.next = None
        self.prev = None
         
# Function to find number of connected
# components using a doubly linked list
# and a reference array
def func_connComp(head_ref, refArr, n):
     
    # Base case when the doubly
    # linked list is empty
    if (head_ref == None):
        return 0;
  
    # Initialise connectedComponents to zero
    connectedComponents = 0;
  
    # Initialise an unordered set
    refSet = set()
  
    # Push the first element of the
    # refArr in the refSet and
    # set the connectedComponents to 1
    refSet.add(refArr[0]);
    connectedComponents += 1
  
    # Loop over all the elements of the refArr
    for i in range(1, n):
  
        # add each reference node to the refSet
        refSet.add(refArr[i]);
  
        # If the reference node is the head of the linked list
        if (refArr[i].prev == None):
  
            # when next sibling of the head node is
            # not in the refSet
            if (refArr[i].next not in refSet):
                connectedComponents += 1
  
        # If the reference node is the
        # last node of the linked list'''
        elif (refArr[i].next == None):
  
            # when previous sibling of the
            # node is not in the refSet
            if (refArr[i].next not in refSet):
                connectedComponents += 1
              
        # the case when both previous and
        # next siblings of the current node
        # are in the refSet
        elif (refArr[i].prev in refSet
              and refArr[i].next in refSet):
            connectedComponents -= 1
             
        # the case when previous and next
        # siblings of the current node
        # are not in the refSet'''
        elif (refArr[i].prev not in refSet
              and refArr[i].next not in refSet):
            connectedComponents += 1
           
    return connectedComponents;
  
# Function to add a node at the
# beginning of the Doubly Linked List
def push(head_ref, new_data):
 
    ''' allocate node '''
    new_node = Node()
    current_node = new_node;
     
    ''' put in the data '''
    new_node.data = new_data;
  
    ''' since we are adding at the beginning,
    prev is always None '''
    new_node.prev = None;
  
    ''' link the old list of the new node '''
    new_node.next = (head_ref);
  
    ''' change prev of head node to new node '''
    if ((head_ref) != None):
        (head_ref).prev = new_node;
  
    ''' move the head to point to the new node '''
    (head_ref) = new_node;
    return current_node, head_ref;
  
# Function to print nodes in a given
# doubly linked list
def printList(node):
    while (node != None):
        print(node.data, end = ' ');
        node = node.next;
         
# Driver code
if __name__=='__main__':
  
    # Start with the empty list
    head = None;
  
    # Let us create a linked list to test
    # the functions so as to find number
    # of Connected Components Created a
    # doubly linked list: 1 <. 7 <. 10 <. 5 <. 4 <. 2
    ref_to_nodeN2, head = push(head, 2);
    ref_to_nodeN4, head = push(head, 4)
    ref_to_nodeN5, head = push(head, 5)
    ref_to_nodeN10, head = push(head, 10)
    ref_to_nodeN7, head = push(head, 7)
    ref_to_nodeN1, head = push(head, 1)  
    refArr = [ref_to_nodeN5, ref_to_nodeN2, ref_to_nodeN7, ref_to_nodeN1]
  
    # This function will return the number
    # of connected components of doubly linked list
    connectedComponents = func_connComp(head, refArr, 4);
    print("Total number of connected components are ", connectedComponents)
 
  # This code is contributed by rutvik_56


C#




// C# program to find number
// of Connected Components in a doubly linked list.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
 
// Node of the doubly linked list
class Node {
    public int data;
    public Node next;
    public Node prev;
}
 
 
class HelloWorld {
     
     
    // Function to find number of connected
    // components using a doubly linked list
    // and a reference array
    public static int func_connComp(Node head_ref, Node[] refArr, int n)
    {
        // Base case when the doubly
        // linked list is empty
        if (head_ref == null) {
            return 0;
        }
 
        // Initialise connectedComponents to zero
        int connectedComponents = 0;
 
        // Initialise an unordered set
        HashSet<Node> refSet = new HashSet<Node>();
 
        // Push the first element of the
        // refArr in the refSet and
        // set the connectedComponents to 1
        refSet.Add(refArr[0]);
        connectedComponents = connectedComponents + 1;
 
        // Loop over all the elements of the refArr
        for (int i = 1; i < n; i++) {
 
          // insert each reference node to the refSet
          refSet.Add(refArr[i]);
 
          // If the reference node is the head of the
          // linked list
          if (refArr[i].prev == null) {
 
            // when next sibling of the head node is
            // not in the refSet
            if (refSet.Contains(refArr[i].next) == true) {
              connectedComponents++;
            }
          }
 
          // If the reference node is the
          // last node of the linked list*/
          else if (refArr[i].next == null) {
 
            // when previous sibling of the
            // node is not in the refSet
            if (refSet.Contains(refArr[i].next) == true) {
              connectedComponents++;
            }
          }
 
      // the case when both previous and
      // next siblings of the current node
      // are in the refSet
      else if (refSet.Contains(refArr[i].prev)
               && refSet.Contains(refArr[i].next)) {
        connectedComponents--;
      }
 
      /*the case when previous and next
            // siblings of the current node
            // are not in the refSet*/
      else if (!refSet.Contains(refArr[i].prev)
               && !refSet.Contains(refArr[i].next)) {
        connectedComponents++;
      }
    }
        return connectedComponents;
    }
    // Function to insert a node at the
    // beginning of the Doubly Linked List
    public static Node push(int new_data)
    {
        /* allocate node */
        Node new_node = new Node();
 
        Node current_node = new_node;
        /* put in the data */
        new_node.data = new_data;
 
        /* since we are adding at the beginning,
            prev is always null */
        new_node.prev = null;
 
        /* link the old list of the new node */
        new_node.next = head;
 
        /* change prev of head node to new node */
        if ((head) != null)
          head.prev = new_node;
 
        /* move the head to point to the new node */
        head = new_node;
 
        return current_node;
    }
     
     
    // Function to print nodes in a given
    // doubly linked list
    public static void printList(Node node)
    {
        while (node != null) {
          Console.Write(node.data + " ");
          node = node.next;
        }
    }
     
    // Start with the empty list
    static Node head = null;
     
    static void Main() {
        // Let us create a linked list to test
        // the functions so as to find number
        // of Connected Components Created a
        // doubly linked list: 1 <. 7 <. 10 <. 5 <. 4 <. 2
        Node ref_to_nodeN2 = push(2);
        Node ref_to_nodeN4 = push(4);
        Node ref_to_nodeN5 = push(5);
        Node ref_to_nodeN10 = push(10);
        Node ref_to_nodeN7 = push(7);
        Node ref_to_nodeN1 = push(1);
 
        Node[] refArr = { ref_to_nodeN5, ref_to_nodeN2,
                         ref_to_nodeN7, ref_to_nodeN1 };
 
        // This function will return the number
        // of connected components of doubly linked list
        int connectedComponents
          = func_connComp(head, refArr, 4);
 
        Console.WriteLine("Total number of connected components are " + connectedComponents);
    }
}
 
// The code is contributed by Arushi Jindal.


Javascript




// A Javascript program to find number
// of Connected Components in a doubly linked list.
// Node of the doubly linked list
class Node {
    constructor() {
        this.data = 0;
        this.next = null;
        this.prev = null;
    }
}
 
// Function to find number of connected
// components using a doubly linked list
// and a reference array
function func_connComp(head_ref, refArr, n) {
    // Base case when the doubly
    // linked list is empty
    if (head_ref === null) {
        return 0;
    }
 
    // Initialize connectedComponents to zero
    let connectedComponents = 0;
 
    // Initialize an Set
    let refSet = new Set();
 
    // Push the first element of the
    // refArr in the refSet and
    // set the connectedComponents to 1
    refSet.add(refArr[0]);
    connectedComponents += 1;
 
    // Loop over all the elements of the refArr
    for (let i = 1; i < n; i++) {
        // add each reference node to the refSet
        refSet.add(refArr[i]);
 
        // If the reference node is the head of the linked list
        if (refArr[i].prev === null) {
            // when next sibling of the head node is
            // not in the refSet
            if (!refSet.has(refArr[i].next)) {
                connectedComponents += 1;
            }
        }
        // If the reference node is the
        // last node of the linked list'''
        else if (refArr[i].next === null) {
            // when previous sibling of the
            // node is not in the refSet
            if (!refSet.has(refArr[i].prev)) {
                connectedComponents += 1;
            }
        }
        // the case when both previous and
        // next siblings of the current node
        // are in the refSet
        else if (
            refSet.has(refArr[i].prev) &&
            refSet.has(refArr[i].next)
        ) {
            connectedComponents -= 1;
        }
        // the case when previous and next
        // siblings of the current node
        // are not in the refSet'''
        else if (
            !refSet.has(refArr[i].prev) &&
            !refSet.has(refArr[i].next)
        ) {
            connectedComponents += 1;
        }
    }
    return connectedComponents;
}
// Function to insert a node at the
// beginning of the Doubly Linked List
function push(headRef, newData) {
    // allocate node
    var newNode = {};
    var currentNode = newNode;
 
    // put in the data
    newNode.data = newData;
 
    /* since we are adding at the beginning,
    prev is always NULL */
    newNode.prev = null;
 
    // link the old list of the new node
    newNode.next = headRef;
 
    // change prev of head node to new node
    if (headRef !== null) {
        headRef.prev = newNode;
    }
 
    // move the head to point to the new node
    headRef = newNode;
    return {
        currentNode: currentNode,
        headRef: headRef
    };
}
 
// Function to print nodes in a given
// doubly linked list
function printList(node) {
    while (node !== null) {
        console.log(node.data);
        node = node.next;
    }
}
 
// Driver code
(function() {
    // Start with the empty list
    var head = null;
 
    // Let us create a linked list to test
    // the functions so as to find number
    // of Connected Components Created a
    // doubly linked list: 1 <-> 7 <-> 10 <-> 5 <-> 4 <-> 2
    var refToNodeN2AndHead = push(head, 2);
    head = refToNodeN2AndHead.headRef;
    var refToNodeN4AndHead = push(head, 4);
    head = refToNodeN4AndHead.headRef;
    var refToNodeN5AndHead = push(head, 5);
    head = refToNodeN5AndHead.headRef;
    var refToNodeN10AndHead = push(head, 10);
    head = refToNodeN10AndHead.headRef;
    var refToNodeN7AndHead = push(head, 7);
    head = refToNodeN7AndHead.headRef;
    var refToNodeN1AndHead = push(head, 1);
    head = refToNodeN1AndHead.headRef;
    var refArr = [refToNodeN5AndHead.currentNode, refToNodeN2AndHead.currentNode, refToNodeN7AndHead.currentNode, refToNodeN1AndHead.currentNode];
 
    // This function will return the number
    // of connected components of doubly linked list
    var connectedComponents = func_connComp(head, refArr, 4);
    console.log("Total number of connected components are ", connectedComponents);
})();


Output

Total number of connected components are 3

Complexity Analysis:

  • Time Complexity: O(m) 
  • Space Complexity: O(m) Where, m = size of the reference array ‘refArr 


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