Union and Intersection of two Linked List using Merge Sort
Last Updated :
10 Sep, 2024
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);
OutputUnion: 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.
Similar Reads
Merge Sort - Data Structure and Algorithms Tutorials Merge sort is a popular sorting algorithm known for its efficiency and stability. It follows the divide-and-conquer approach. It works by recursively dividing the input array into two halves, recursively sorting the two halves and finally merging them back together to obtain the sorted array. Merge
14 min read
Merge sort in different languages
C Program for Merge SortMerge Sort is a comparison-based sorting algorithm that works by dividing the input array into two halves, then calling itself for these two halves, and finally it merges the two sorted halves. In this article, we will learn how to implement merge sort in C language.What is Merge Sort Algorithm?Merg
3 min read
C++ Program For Merge SortMerge Sort is a comparison-based sorting algorithm that uses divide and conquer paradigm to sort the given dataset. It divides the dataset into two halves, calls itself for these two halves, and then it merges the two sorted halves.In this article, we will learn how to implement merge sort in a C++
4 min read
Java Program for Merge SortMerge Sort is a divide-and-conquer algorithm. It divides the input array into two halves, calls itself the two halves, and then merges the two sorted halves. The merge() function is used for merging two halves. The merge(arr, l, m, r) is a key process that assumes that arr[l..m] and arr[m+1..r] are
3 min read
Merge Sort in PythonMerge Sort is a Divide and Conquer algorithm. It divides input array in two halves, calls itself for the two halves and then merges the two sorted halves. The merge() function is used for merging two halves. The merge(arr, l, m, r) is key process that assumes that arr[l..m] and arr[m+1..r] are sorte
4 min read
Merge Sort using Multi-threadingMerge Sort is a popular sorting technique which divides an array or list into two halves and then start merging them when sufficient depth is reached. Time complexity of merge sort is O(nlogn).Threads are lightweight processes and threads shares with other threads their code section, data section an
14 min read
Variations of Merge Sort
3-way Merge SortMerge Sort is a divide-and-conquer algorithm that recursively splits an array into two halves, sorts each half, and then merges them. A variation of this is 3-way Merge Sort, where instead of splitting the array into two parts, we divide it into three equal parts. In traditional Merge Sort, the arra
13 min read
Iterative Merge SortGiven an array of size n, the task is to sort the given array using iterative merge sort.Examples:Input: arr[] = [4, 1, 3, 9, 7]Output: [1, 3, 4, 7, 9]Explanation: The output array is sorted.Input: arr[] = [1, 3 , 2]Output: [1, 2, 3]Explanation: The output array is sorted.You can refer to Merge Sort
9 min read
In-Place Merge SortImplement Merge Sort i.e. standard implementation keeping the sorting algorithm as in-place. In-place means it does not occupy extra memory for merge operation as in the standard case. Examples: Input: arr[] = {2, 3, 4, 1} Output: 1 2 3 4 Input: arr[] = {56, 2, 45} Output: 2 45 56 Approach 1: Mainta
15+ min read
In-Place Merge Sort | Set 2Given an array A[] of size N, the task is to sort the array in increasing order using In-Place Merge Sort. Examples: Input: A = {5, 6, 3, 2, 1, 6, 7}Output: {1, 2, 3, 5, 6, 6, 7} Input: A = {2, 3, 4, 1}Output: {1, 2, 3, 4} Approach: The idea is to use the inplace_merge() function to merge the sorted
7 min read
Merge Sort with O(1) extra space merge and O(n log n) time [Unsigned Integers Only]We have discussed Merge sort. How to modify the algorithm so that merge works in O(1) extra space and algorithm still works in O(n Log n) time. We may assume that the input values are integers only. Examples: Input : 5 4 3 2 1 Output : 1 2 3 4 5 Input : 999 612 589 856 56 945 243 Output : 56 243 589
10 min read
Merge Sort in Linked List
Find a permutation that causes worst case of Merge Sort Given a set of elements, find which permutation of these elements would result in worst case of Merge Sort.Asymptotically, merge sort always takes O(n Log n) time, but the cases that require more comparisons generally take more time in practice. We basically need to find a permutation of input eleme
12 min read
How to make Mergesort to perform O(n) comparisons in best case? As we know, Mergesort is a divide and conquer algorithm that splits the array to halves recursively until it reaches an array of the size of 1, and after that it merges sorted subarrays until the original array is fully sorted. Typical implementation of merge sort works in O(n Log n) time in all thr
3 min read
Concurrent Merge Sort in Shared Memory Given a number 'n' and a n numbers, sort the numbers using Concurrent Merge Sort. (Hint: Try to use shmget, shmat system calls).Part1: The algorithm (HOW?) Recursively make two child processes, one for the left half, one of the right half. If the number of elements in the array for a process is less
10 min read
Visualization of Merge Sort
Some problems on Merge Sort
Count Inversions of an ArrayGiven an integer array arr[] of size n, find the inversion count in the array. Two array elements arr[i] and arr[j] form an inversion if arr[i] > arr[j] and i < j.Note: Inversion Count for an array indicates that how far (or close) the array is from being sorted. If the array is already sorted
15+ min read
Count of smaller elements on right side of each element in an Array using Merge sortGiven an array arr[] of N integers, the task is to count the number of smaller elements on the right side for each of the element in the array Examples: Input: arr[] = {6, 3, 7, 2} Output: 2, 1, 1, 0 Explanation: Smaller elements after 6 = 2 [3, 2] Smaller elements after 3 = 1 [2] Smaller elements a
12 min read
Sort a nearly sorted (or K sorted) arrayGiven an array arr[] and a number k . The array is sorted in a way that every element is at max k distance away from it sorted position. It means if we completely sort the array, then the index of the element can go from i - k to i + k where i is index in the given array. Our task is to completely s
6 min read
Median of two Sorted Arrays of Different SizesGiven two sorted arrays, a[] and b[], the task is to find the median of these sorted arrays. Assume that the two sorted arrays are merged and then median is selected from the combined array.This is an extension of Median of two sorted arrays of equal size problem. Here we handle arrays of unequal si
15+ min read
Merge k Sorted ArraysGiven K sorted arrays, merge them and print the sorted output.Examples:Input: K = 3, arr = { {1, 3, 5, 7}, {2, 4, 6, 8}, {0, 9, 10, 11}}Output: 0 1 2 3 4 5 6 7 8 9 10 11 Input: k = 4, arr = { {1}, {2, 4}, {3, 7, 9, 11}, {13} }Output: 1 2 3 4 7 9 11 13Table of ContentNaive - Concatenate all and SortU
15+ min read
Merge K sorted arrays of different sizes | ( Divide and Conquer Approach )Given k sorted arrays of different length, merge them into a single array such that the merged array is also sorted.Examples: Input : {{3, 13}, {8, 10, 11} {9, 15}} Output : {3, 8, 9, 10, 11, 13, 15} Input : {{1, 5}, {2, 3, 4}} Output : {1, 2, 3, 4, 5} Let S be the total number of elements in all th
8 min read
Merge K sorted linked listsGiven k sorted linked lists of different sizes, the task is to merge them all maintaining their sorted order.Examples: Input: Output: Merged lists in a sorted order where every element is greater than the previous element.Input: Output: Merged lists in a sorted order where every element is greater t
15+ min read
Union and Intersection of two Linked List using Merge SortGiven 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 -
15+ min read
Sorting by combining Insertion Sort and Merge Sort algorithmsInsertion sort: The array is virtually split into a sorted and an unsorted part. Values from the unsorted part are picked and placed at the correct position in the sorted part.Advantages: Following are the advantages of insertion sort: If the size of the list to be sorted is small, insertion sort ru
2 min read
Find array with k number of merge sort callsGiven two numbers n and k, find an array containing values in [1, n] and requires exactly k calls of recursive merge sort function. Examples: Input : n = 3 k = 3 Output : a[] = {2, 1, 3} Explanation: Here, a[] = {2, 1, 3} First of all, mergesort(0, 3) will be called, which then sets mid = 1 and call
6 min read
Difference of two Linked Lists using Merge sortGiven two Linked List, the task is to create a Linked List to store the difference of Linked List 1 with Linked List 2, i.e. the elements present in List 1 but not in List 2.Examples: Input: List1: 10 -> 15 -> 4 ->20, List2: 8 -> 4 -> 2 -> 10 Output: 15 -> 20 Explanation: In the
14 min read