Open In App

Union and Intersection of two Linked List using Merge Sort

Last Updated : 10 Sep, 2024
Suggest changes
Share
Like Article
Like
Report

Given two singly Linked Lists, create union and intersection lists that contain the union and intersection of the elements present in the given lists. Each of the two lists contains distinct node values.

Note: The order of elements in output lists doesn't matter.

Examples:

Input:
head1: 10 -> 15 -> 4 -> 20
head2: 8 -> 4 -> 2 -> 10
Output:
Union List: 2 -> 4 -> 8 -> 10 -> 15 -> 20
Intersection List: 4 -> 10
Explanation: In these two lists 4 and 10 nodes are common. The union lists contain all the unique nodes of both lists.

Input:
head1 : 1 -> 2 -> 3 -> 4
head2 : 3 -> 4 -> 8 -> 10
Output:
Union List: 1 -> 2 -> 3 -> 4 -> 8 -> 10
Intersection List: 3 -> 4
Explanation: In these two lists 3 and 4 nodes are common. The union lists contain all the unique nodes of both lists.

Approach:

The idea is to sort the given lists using merge sort, then we linearly search both sorted lists to obtain the union and intersection. By Keeping two pointers (initially pointing to the first node of the respective lists) compare the node values :

  • If the values are equal, add the value to both the union and intersection lists, then move both pointers to the next node.
  • else if the values are not equal, insert the smaller value into the union list and move the corresponding pointer to the next node.
  • If one of the pointers becomes null, traverse the remaining nodes of the other list and add them to the union list.
C++
// C++ program to find union and intersection of // two unsored linked lists in O(nlogn) time. #include <iostream> using namespace std; class Node {  public:  int data;  Node *next;  Node(int x) {  data = x;  next = nullptr;  } }; // Function to split the singly // linked list into two halves Node *split(Node *head) {  Node *fast = head;  Node *slow = head;  // Move fast pointer two steps and slow pointer  // one step until fast reaches the end  while (fast != nullptr && fast->next != nullptr) {  fast = fast->next->next;  if (fast != nullptr) {  slow = slow->next;  }  }  // Split the list into two halves  Node *temp = slow->next;  slow->next = nullptr;  return temp; } // Function to merge two sorted singly linked lists Node *merge(Node *head1, Node *head2) {  // If either list is empty, return the other list  if (head1 == nullptr) {  return head2;  }  if (head2 == nullptr) {  return head1;  }  // Pick the smaller value between head1 and head2 nodes  if (head1->data < head2->data) {  // Recursively merge the rest of the lists and  // link the result to the current node  head1->next = merge(head1->next, head2);  return head1;  }  else {  // Recursively merge the rest of the lists  // and link the result to the current node  head2->next = merge(head1, head2->next);  return head2;  } } // Function to perform merge sort on a singly linked list Node *MergeSort(Node *head) {  // Base case: if the list is empty or has only one node,  // it's already sorted  if (head == nullptr || head->next == nullptr) {  return head;  }  // Split the list into two halves  Node *second = split(head);  // Recursively sort each half  head = MergeSort(head);  second = MergeSort(second);  // Merge the two sorted halves  return merge(head, second); } // Function to get the union of two linked lists Node *getUnion(Node *head1, Node *head2) {  // Initialize head to a dummy node with data -1  Node *head = new Node(-1);  Node *tail = head;  // Merge both sorted lists to create the union list  while (head1 != nullptr && head2 != nullptr) {  // Skip duplicates in the first list  while (head1->next != nullptr  && head1->data == head1->next->data) {  head1 = head1->next;  }    // Skip duplicates in the second list  while (head2->next != nullptr   && head2->data == head2->next->data) {  head2 = head2->next;  }  if (head1->data < head2->data) {    // Add head1 data to union list  tail->next = new Node(head1->data);  tail = tail->next;  head1 = head1->next;  }  else if (head1->data > head2->data) {    // Add head2 data to union list  tail->next = new Node(head2->data);  tail = tail->next;  head2 = head2->next;  }  else {    // Add common data to union list  tail->next = new Node(head1->data);  tail = tail->next;  head1 = head1->next;  head2 = head2->next;  }  }  // Add remaining nodes from head1 or head2  while (head1 != nullptr) {  // Skip duplicates in the first list  while (head1->next != nullptr   && head1->data == head1->next->data) {  head1 = head1->next;  }  tail->next = new Node(head1->data);  tail = tail->next;  head1 = head1->next;  }  while (head2 != nullptr) {  // Skip duplicates in the second list  while (head2->next != nullptr  && head2->data == head2->next->data) {  head2 = head2->next;  }  tail->next = new Node(head2->data);  tail = tail->next;  head2 = head2->next;  }  // Skip the dummy node  return head->next; } // Function to get the intersection of two linked lists Node *getIntersection(Node *head1, Node *head2) {    // Initialize head to a dummy node with data -1  Node *head = new Node(-1);  Node *tail = head;  // Traverse both sorted lists to find common elements  while (head1 != nullptr && head2 != nullptr) {    // Skip duplicates in the first list  while (head1->next != nullptr   && head1->data == head1->next->data) {  head1 = head1->next;  }    // Skip duplicates in the second list  while (head2->next != nullptr   && head2->data == head2->next->data) {  head2 = head2->next;  }  if (head1->data < head2->data) {  head1 = head1->next;  }  else if (head1->data > head2->data) {  head2 = head2->next;  }  else {    // Common element found  tail->next = new Node(head1->data);  tail = tail->next;  head1 = head1->next;  head2 = head2->next;  }  }  // Skip the dummy node  return head->next; } void printList(Node *head) {  Node *curr = head;  while (curr != nullptr) {  cout << curr->data << " ";  curr = curr->next;  }  cout << endl; } int main() {    // Create two hard-coded singly linked lists:  // List 1: 10 -> 15 -> 4 -> 20  Node *head1 = new Node(10);  head1->next = new Node(15);  head1->next->next = new Node(4);  head1->next->next->next = new Node(20);  // List 2: 8 -> 4 -> 2 -> 10  Node *head2 = new Node(8);  head2->next = new Node(4);  head2->next->next = new Node(2);  head2->next->next->next = new Node(10);  // Sort the linked lists using mergeSort  head1 = MergeSort(head1);  head2 = MergeSort(head2);    //head1 and head2 List becomes sorted  Node *unionList = getUnion(head1, head2);  Node *intersectionList = getIntersection(head1, head2);  cout << "Union: ";  printList(unionList);  cout << "Intersection: ";  printList(intersectionList);  return 0; } 
C
// C program to find union and intersection of // two unsored linked lists in O(nlogn) time. #include <stdio.h> #include <stdlib.h> struct Node {  int data;  struct Node *next; }; struct Node *createNode(int data); // Function to split the singly linked list into two halves struct Node *split(struct Node *head) {  struct Node *fast = head;  struct Node *slow = head;  // Move fast pointer two steps and slow pointer  // one step until fast reaches the end  while (fast != NULL && fast->next != NULL) {  fast = fast->next->next;  if (fast != NULL) {  slow = slow->next;  }  }  // Split the list into two halves  struct Node *temp = slow->next;  slow->next = NULL;  return temp; } // Function to merge two sorted singly linked lists struct Node *merge(struct Node *head1, struct Node *head2) {    // If either list is empty, return the other list  if (head1 == NULL)  return head2;  if (head2 == NULL)  return head1;  // Pick the smaller value between head1 and head2 nodes  if (head1->data < head2->data) {    // Recursively merge the rest of the lists and  // link the result to the current node  head1->next = merge(head1->next, head2);  return head1;  }  else {    // Recursively merge the rest of the lists  // and link the result to the current node  head2->next = merge(head1, head2->next);  return head2;  } } // Function to perform merge sort on a singly linked list struct Node *mergeSort(struct Node *head) {    // Base case: if the list is empty or has only one node,  // it's already sorted  if (head == NULL || head->next == NULL)  return head;  // Split the list into two halves  struct Node *second = split(head);  // Recursively sort each half  head = mergeSort(head);  second = mergeSort(second);  // Merge the two sorted halves  return merge(head, second); } // Function to get the union of two linked lists struct Node *getUnion(struct Node *head1, struct Node *head2) {    // Initialize head to a dummy node with data -1  struct Node *head = createNode(-1);  struct Node *tail = head;  // Merge both sorted lists to create the union list  while (head1 != NULL   && head2 != NULL) {    // Skip duplicates in the first list  while (head1->next != NULL   && head1->data == head1->next->data) {  head1 = head1->next;  }    // Skip duplicates in the second list  while (head2->next != NULL   && head2->data == head2->next->data) {  head2 = head2->next;  }  if (head1->data < head2->data) {    // Add head1 data to union list  tail->next = createNode(head1->data);  tail = tail->next;  head1 = head1->next;  }  else if (head1->data > head2->data) {    // Add head2 data to union list  tail->next = createNode(head2->data);  tail = tail->next;  head2 = head2->next;  }  else {    // Add common data to union list  tail->next = createNode(head1->data);  tail = tail->next;  head1 = head1->next;  head2 = head2->next;  }  }  // Add remaining nodes from head1 or head2  while (head1 != NULL) {    // Skip duplicates in the first list  while (head1->next != NULL   && head1->data == head1->next->data) {  head1 = head1->next;  }  tail->next = createNode(head1->data);  tail = tail->next;  head1 = head1->next;  }  while (head2 != NULL) {    // Skip duplicates in the second list  while (head2->next != NULL   && head2->data == head2->next->data) {  head2 = head2->next;  }  tail->next = createNode(head2->data);  tail = tail->next;  head2 = head2->next;  }  // Skip the dummy node  return head->next; } // Function to get the intersection of two linked lists struct Node *getIntersection(struct Node *head1, struct Node *head2) {    // Initialize head to a dummy node with data -1  struct Node *head = createNode(-1);  struct Node *tail = head;  // Traverse both sorted lists to find common elements  while (head1 != NULL && head2 != NULL) {    // Skip duplicates in the first list  while (head1->next != NULL && head1->data == head1->next->data) {  head1 = head1->next;  }    // Skip duplicates in the second list  while (head2->next != NULL && head2->data == head2->next->data) {  head2 = head2->next;  }  if (head1->data < head2->data) {  head1 = head1->next;  }  else if (head1->data > head2->data) {  head2 = head2->next;  }  else {  // Common element found  tail->next = createNode(head1->data);  tail = tail->next;  head1 = head1->next;  head2 = head2->next;  }  }  // Skip the dummy node  return head->next; } void printList(struct Node *head) {  struct Node *curr = head;  while (curr != NULL) {  printf("%d ", curr->data);  curr = curr->next;  }  printf("\n"); } struct Node *createNode(int data) {  struct Node *newNode =   (struct Node *)malloc(sizeof(struct Node));  newNode->data = data;  newNode->next = NULL;  return newNode; } int main() {    // Create two hard-coded singly linked lists:  // List 1: 10 -> 15 -> 4 -> 20  struct Node *head1 = createNode(10);  head1->next = createNode(15);  head1->next->next = createNode(4);  head1->next->next->next = createNode(20);  // List 2: 8 -> 4 -> 2 -> 10  struct Node *head2 = createNode(8);  head2->next = createNode(4);  head2->next->next = createNode(2);  head2->next->next->next = createNode(10);  // Sort the linked lists  head1 = mergeSort(head1);  head2 = mergeSort(head2);    //head1 and head2 List becomes sorted  struct Node *unionList = getUnion(head1, head2);  struct Node *intersectionList = getIntersection(head1, head2);  printf("Union: ");  printList(unionList);  printf("Intersection: ");  printList(intersectionList);  return 0; } 
Java
// Java program to find union and intersection of  // two unsored linked lists in O(nlogn) time. class Node {  int data;  Node next;  Node(int data) {  this.data = data;  this.next = null;  } } class GfG {  // Function to split the singly linked list  // into two halves  static Node split(Node head) {  Node fast = head;  Node slow = head;  // Move fast pointer two steps and slow pointer  // one step until fast reaches the end  while (fast != null && fast.next != null) {  fast = fast.next.next;  if (fast != null) {  slow = slow.next;  }  }  // Split the list into two halves  Node temp = slow.next;  slow.next = null;  return temp;  }  // Function to merge two sorted singly linked lists  static Node merge(Node head1, Node head2) {    // If either list is empty, return the other list  if (head1 == null) return head2;  if (head2 == null) return head1;  // Pick the smaller value between  // head1 and head2 nodes  if (head1.data < head2.data) {    // Recursively merge the rest of the lists and  // link the result to the current node  head1.next = merge(head1.next, head2);  return head1;  } else {    // Recursively merge the rest of the lists  // and link the result to the current node  head2.next = merge(head1, head2.next);  return head2;  }  }  // Function to perform merge sort on   // a singly linked list  static Node mergeSort(Node head) {    // Base case: if the list is empty or has only one node,   // it's already sorted  if (head == null || head.next == null) return head;  // Split the list into two halves  Node second = split(head);  // Recursively sort each half  head = mergeSort(head);  second = mergeSort(second);  // Merge the two sorted halves  return merge(head, second);  }  // Function to get the union of two linked lists  static Node getUnion(Node head1, Node head2) {    // Initialize head to a dummy node with data -1  Node head = new Node(-1);  Node tail = head;  // Merge both sorted lists to create the union list  while (head1 != null && head2 != null) {    // Skip duplicates in the first list  while (head1.next != null && head1.data == head1.next.data) {  head1 = head1.next;  }    // Skip duplicates in the second list  while (head2.next != null && head2.data == head2.next.data) {  head2 = head2.next;  }  if (head1.data < head2.data) {    // Add head1 data to union list  tail.next = new Node(head1.data);  tail = tail.next;  head1 = head1.next;  } else if (head1.data > head2.data) {    // Add head2 data to union list  tail.next = new Node(head2.data);  tail = tail.next;  head2 = head2.next;  } else {    // Add common data to union list  tail.next = new Node(head1.data);  tail = tail.next;  head1 = head1.next;  head2 = head2.next;  }  }  // Add remaining nodes from head1 or head2  while (head1 != null) {    // Skip duplicates in the first list  while (head1.next != null   && head1.data == head1.next.data) {  head1 = head1.next;  }  tail.next = new Node(head1.data);  tail = tail.next;  head1 = head1.next;  }  while (head2 != null) {    // Skip duplicates in the second list  while (head2.next != null && head2.data == head2.next.data) {  head2 = head2.next;  }  tail.next = new Node(head2.data);  tail = tail.next;  head2 = head2.next;  }  // Skip the dummy node  return head.next;  }  // Function to get the intersection of two linked lists  static Node getIntersection(Node head1, Node head2) {    // Initialize head to a dummy node with data -1  Node head = new Node(-1);  Node tail = head;  // Traverse both sorted lists to find common elements  while (head1 != null && head2 != null) {    // Skip duplicates in the first list  while (head1.next != null && head1.data == head1.next.data) {  head1 = head1.next;  }    // Skip duplicates in the second list  while (head2.next != null && head2.data == head2.next.data) {  head2 = head2.next;  }  if (head1.data < head2.data) {  head1 = head1.next;  } else if (head1.data > head2.data) {  head2 = head2.next;  } else {    // Common element found  tail.next = new Node(head1.data);  tail = tail.next;  head1 = head1.next;  head2 = head2.next;  }  }  // Skip the dummy node  return head.next;  }  static void printList(Node head) {  Node curr = head;  while (curr != null) {  System.out.print(curr.data + " ");  curr = curr.next;  }  System.out.println();  }  public static void main(String[] args) {    // Create two hard-coded singly linked lists:  // List 1: 10 -> 15 -> 4 -> 20  Node head1 = new Node(10);  head1.next = new Node(15);  head1.next.next = new Node(4);  head1.next.next.next = new Node(20);  // List 2: 8 -> 4 -> 2 -> 10  Node head2 = new Node(8);  head2.next = new Node(4);  head2.next.next = new Node(2);  head2.next.next.next = new Node(10);  // Sort the linked lists using merSort  head1 = mergeSort(head1);  head2 = mergeSort(head2);   //head1 and head2 List becomes sorted  Node unionList = getUnion(head1, head2);  Node intersectionList = getIntersection(head1, head2);  System.out.print("Union: ");  printList(unionList);  System.out.print("Intersection: ");  printList(intersectionList);  } } 
Python
# Python program to find union and intersection of  # two unsored linked lists in O(nlogn) time. class Node: def __init__(self, x): self.data = x self.next = None # Function to split the singly linked  # list into two halves def split(head): fast = head slow = head # Move fast pointer two steps and slow pointer # one step until fast reaches the end while fast and fast.next: fast = fast.next.next if fast: slow = slow.next # Split the list into two halves temp = slow.next slow.next = None return temp # Function to merge two sorted singly linked lists def merge(head1, head2): # If either list is empty, return the other list if head1 is None: return head2 if head2 is None: return head1 # Pick the smaller value between head1 and head2 nodes if head1.data < head2.data: # Recursively merge the rest of the lists and # link the result to the current node head1.next = merge(head1.next, head2) return head1 else: # Recursively merge the rest of the lists # and link the result to the current node head2.next = merge(head1, head2.next) return head2 # Function to perform merge sort  # on a singly linked list def mergeSort(head): # Base case: if the list is empty or has only one node,  # it's already sorted if head is None or head.next is None: return head # Split the list into two halves second = split(head) # Recursively sort each half head = mergeSort(head) second = mergeSort(second) # Merge the two sorted halves return merge(head, second) # Function to get the union of two linked lists def getUnion(head1, head2): # Initialize head to a dummy node with data -1 head = Node(-1) tail = head # Merge both sorted lists to create the union list while head1 and head2: # Skip duplicates in the first list while head1.next and head1.data == head1.next.data: head1 = head1.next # Skip duplicates in the second list while head2.next and head2.data == head2.next.data: head2 = head2.next if head1.data < head2.data: # Add head1 data to union list tail.next = Node(head1.data) tail = tail.next head1 = head1.next elif head1.data > head2.data: # Add head2 data to union list tail.next = Node(head2.data) tail = tail.next head2 = head2.next else: # Add common data to union list tail.next = Node(head1.data) tail = tail.next head1 = head1.next head2 = head2.next # Add remaining nodes from head1 or head2 while head1: # Skip duplicates in the first list while head1.next and head1.data == head1.next.data: head1 = head1.next tail.next = Node(head1.data) tail = tail.next head1 = head1.next while head2: # Skip duplicates in the second list while head2.next and head2.data == head2.next.data: head2 = head2.next tail.next = Node(head2.data) tail = tail.next head2 = head2.next # Skip the dummy node return head.next # Function to get the intersection of two linked lists def getIntersection(head1, head2): # Initialize head to a dummy node with data -1 head = Node(-1) tail = head # Traverse both sorted lists to find common elements while head1 and head2: # Skip duplicates in the first list while head1.next and head1.data == head1.next.data: head1 = head1.next # Skip duplicates in the second list while head2.next and head2.data == head2.next.data: head2 = head2.next if head1.data < head2.data: head1 = head1.next elif head1.data > head2.data: head2 = head2.next else: # Common element found tail.next = Node(head1.data) tail = tail.next head1 = head1.next head2 = head2.next # Skip the dummy node return head.next def printList(head): curr = head while curr: print(curr.data, end=' ') curr = curr.next print() if __name__ == "__main__": # Create two hard-coded singly linked lists: # List 1: 10 -> 15 -> 4 -> 20 head1 = Node(10) head1.next = Node(15) head1.next.next = Node(4) head1.next.next.next = Node(20) # List 2: 8 -> 4 -> 2 -> 10 head2 = Node(8) head2.next = Node(4) head2.next.next = Node(2) head2.next.next.next = Node(10) # Sort the linked lists head1 = mergeSort(head1) head2 = mergeSort(head2) #head1 and head2 List becomes sorted unionList = getUnion(head1, head2) intersectionList = getIntersection(head1, head2) print("Union:", end=' ') printList(unionList) print("Intersection:", end=' ') printList(intersectionList) 
C#
// C# program to find union and intersection of  // two unsored linked lists in O(nlogn) time. using System; class Node {  public int Data;  public Node Next;  public Node(int data) {  this.Data = data;  this.Next = null;  } } class GfG {    // Function to split the singly linked list into two halves  static Node Split(Node head) {  Node fast = head;  Node slow = head;  // Move fast pointer two steps and slow pointer  // one step until fast reaches the end  while (fast != null && fast.Next != null) {  fast = fast.Next.Next;  if (fast != null) {  slow = slow.Next;  }  }  // Split the list into two halves  Node temp = slow.Next;  slow.Next = null;  return temp;  }  // Function to merge two sorted singly linked lists  static Node Merge(Node head1, Node head2) {    // If either list is empty, return the other list  if (head1 == null) return head2;  if (head2 == null) return head1;  // Pick the smaller value between head1 and head2 nodes  if (head1.Data < head2.Data) {    // Recursively merge the rest of the lists and  // link the result to the current node  head1.Next = Merge(head1.Next, head2);  return head1;  } else {    // Recursively merge the rest of the lists  // and link the result to the current node  head2.Next = Merge(head1, head2.Next);  return head2;  }  }  // Function to perform merge sort on a singly linked list  static Node MergeSort(Node head) {    // Base case: if the list is empty or has only one node,   // it's already sorted  if (head == null || head.Next == null) return head;  // Split the list into two halves  Node second = Split(head);  // Recursively sort each half  head = MergeSort(head);  second = MergeSort(second);  // Merge the two sorted halves  return Merge(head, second);  }  // Function to get the union of two linked lists  static Node GetUnion(Node head1, Node head2) {    // Initialize head to a dummy node with data -1  Node head = new Node(-1);  Node tail = head;  // Merge both sorted lists to create the union list  while (head1 != null && head2 != null) {    // Skip duplicates in the first list  while (head1.Next != null && head1.Data == head1.Next.Data) {  head1 = head1.Next;  }    // Skip duplicates in the second list  while (head2.Next != null && head2.Data == head2.Next.Data) {  head2 = head2.Next;  }  if (head1.Data < head2.Data) {    // Add head1 data to union list  tail.Next = new Node(head1.Data);  tail = tail.Next;  head1 = head1.Next;  } else if (head1.Data > head2.Data) {    // Add head2 data to union list  tail.Next = new Node(head2.Data);  tail = tail.Next;  head2 = head2.Next;  } else {    // Add common data to union list  tail.Next = new Node(head1.Data);  tail = tail.Next;  head1 = head1.Next;  head2 = head2.Next;  }  }  // Add remaining nodes from head1 or head2  while (head1 != null) {    // Skip duplicates in the first list  while (head1.Next != null   && head1.Data == head1.Next.Data) {  head1 = head1.Next;  }  tail.Next = new Node(head1.Data);  tail = tail.Next;  head1 = head1.Next;  }  while (head2 != null) {    // Skip duplicates in the second list  while (head2.Next != null   && head2.Data == head2.Next.Data) {  head2 = head2.Next;  }  tail.Next = new Node(head2.Data);  tail = tail.Next;  head2 = head2.Next;  }  // Skip the dummy node  return head.Next;  }  // Function to get the intersection of two linked lists  static Node GetIntersection(Node head1, Node head2) {    // Initialize head to a dummy node with data -1  Node head = new Node(-1);  Node tail = head;  // Traverse both sorted lists to find   // common elements  while (head1 != null && head2 != null) {    // Skip duplicates in the first list  while (head1.Next != null   && head1.Data == head1.Next.Data) {  head1 = head1.Next;  }    // Skip duplicates in the second list  while (head2.Next != null   && head2.Data == head2.Next.Data) {  head2 = head2.Next;  }  if (head1.Data < head2.Data) {  head1 = head1.Next;  } else if (head1.Data > head2.Data) {  head2 = head2.Next;  } else {    // Common element found  tail.Next = new Node(head1.Data);  tail = tail.Next;  head1 = head1.Next;  head2 = head2.Next;  }  }  // Skip the dummy node  return head.Next;  }  static void PrintList(Node head) {  Node curr = head;  while (curr != null) {  Console.Write(curr.Data + " ");  curr = curr.Next;  }  Console.WriteLine();  }  static void Main() {    // Create two hard-coded singly linked lists:  // List 1: 10 -> 15 -> 4 -> 20  Node head1 = new Node(10);  head1.Next = new Node(15);  head1.Next.Next = new Node(4);  head1.Next.Next.Next = new Node(20);  // List 2: 8 -> 4 -> 2 -> 10  Node head2 = new Node(8);  head2.Next = new Node(4);  head2.Next.Next = new Node(2);  head2.Next.Next.Next = new Node(10);  // Sort the linked lists  head1 = MergeSort(head1);  head2 = MergeSort(head2);   //head1 and head2 List becomes sorted  Node unionList = GetUnion(head1, head2);  Node intersectionList = GetIntersection(head1, head2);  Console.Write("Union: ");  PrintList(unionList);  Console.Write("Intersection: ");  PrintList(intersectionList);  } } 
JavaScript
// Javascript program to find union and intersection of  // two unsored linked lists in O(nlogn) time. class Node {  constructor(x) {  this.data = x;  this.next = null;  } } // Function to split the singly linked  // list into two halves function split(head) {  let fast = head;  let slow = head;  // Move fast pointer two steps and slow pointer  // one step until fast reaches the end  while (fast !== null && fast.next !== null) {  fast = fast.next.next;  if (fast !== null) {  slow = slow.next;  }  }  // Split the list into two halves  let temp = slow.next;  slow.next = null;  return temp; } // Function to merge two sorted singly linked lists function merge(head1, head2) {  // If either list is empty, return the other list  if (head1 === null) return head2;  if (head2 === null) return head1;  // Pick the smaller value between head1 and head2 nodes  if (head1.data < head2.data) {    // Recursively merge the rest of the lists and  // link the result to the current node  head1.next = merge(head1.next, head2);  return head1;  } else {    // Recursively merge the rest of the lists  // and link the result to the current node  head2.next = merge(head1, head2.next);  return head2;  } } // Function to perform merge sort on a singly linked list function mergeSort(head) {  // Base case: if the list is empty or has only one node,   // it's already sorted  if (head === null || head.next === null) return head;  // Split the list into two halves  let second = split(head);  // Recursively sort each half  head = mergeSort(head);  second = mergeSort(second);  // Merge the two sorted halves  return merge(head, second); } // Function to get the union of two linked lists function getUnion(head1, head2) {  // Initialize head to a dummy node with data -1  let head = new Node(-1);  let tail = head;  // Merge both sorted lists to create the union list  while (head1 !== null && head2 !== null) {    // Skip duplicates in the first list  while (head1.next !== null   && head1.data === head1.next.data) {  head1 = head1.next;  }    // Skip duplicates in the second list  while (head2.next !== null   && head2.data === head2.next.data) {  head2 = head2.next;  }  if (head1.data < head2.data) {    // Add head1 data to union list  tail.next = new Node(head1.data);  tail = tail.next;  head1 = head1.next;  } else if (head1.data > head2.data) {    // Add head2 data to union list  tail.next = new Node(head2.data);  tail = tail.next;  head2 = head2.next;  } else {    // Add common data to union list  tail.next = new Node(head1.data);  tail = tail.next;  head1 = head1.next;  head2 = head2.next;  }  }  // Add remaining nodes from head1 or head2  while (head1 !== null) {    // Skip duplicates in the first list  while (head1.next !== null   && head1.data === head1.next.data) {  head1 = head1.next;  }  tail.next = new Node(head1.data);  tail = tail.next;  head1 = head1.next;  }  while (head2 !== null) {    // Skip duplicates in the second list  while (head2.next !== null   && head2.data === head2.next.data) {  head2 = head2.next;  }  tail.next = new Node(head2.data);  tail = tail.next;  head2 = head2.next;  }    // Skip the dummy node  return head.next; } // Function to get the intersection of two linked lists function getIntersection(head1, head2) {  // Initialize head to a dummy node with data -1  let head = new Node(-1);  let tail = head;  // Traverse both sorted lists to find common elements  while (head1 !== null && head2 !== null) {    // Skip duplicates in the first list  while (head1.next !== null  && head1.data === head1.next.data) {  head1 = head1.next;  }    // Skip duplicates in the second list  while (head2.next !== null   && head2.data === head2.next.data) {  head2 = head2.next;  }  if (head1.data < head2.data) {  head1 = head1.next;  } else if (head1.data > head2.data) {  head2 = head2.next;  } else {    // Common element found  tail.next = new Node(head1.data);  tail = tail.next;  head1 = head1.next;  head2 = head2.next;  }  }    // Skip the dummy node  return head.next; } function printList(head) {  let curr = head;  while (curr !== null) {  console.log(curr.data, end=' ');  curr = curr.next;  }  console.log(); } // List 1: 10 -> 15 -> 4 -> 20 let head1 = new Node(10); head1.next = new Node(15); head1.next.next = new Node(4); head1.next.next.next = new Node(20); // List 2: 8 -> 4 -> 2 -> 10 let head2 = new Node(8); head2.next = new Node(4); head2.next.next = new Node(2); head2.next.next.next = new Node(10); head1 = mergeSort(head1); head2 = mergeSort(head2); //head1 and head2 List becomes sorted let unionList = getUnion(head1, head2); let intersectionList = getIntersection(head1, head2); console.log("Union:"); printList(unionList); console.log("Intersection:"); printList(intersectionList); 

Output
Union: 2 4 8 10 15 20 Intersection: 4 10 

Time complexity: O(mLogm + nLogn). Time required to sort the lists are nlogn and mlogm and to find union and intersection linear time is required.
Auxiliary Space: O(m + n).

The above approach is not the most optimal solution for this problem. Plese refer to Union and Intersection using Hashing.


Next Article

Similar Reads