Table of Contents
In this article, we will find the union and intersection of two linked lists. We will have a singly linked list, and therefore, each node will have data and a reference to the next node. Moreover, union and intersection are concepts of sets, and in a set, all items are distinct. Therefore, we also assume that the linked list does not have duplicates. Let’s take an example.
The union of two linked lists is a linked list that contains all the items that are in linked list one or linked list two (or both).
The intersection of two linked lists is a list that contains those items that are in both linked lists.
Now that we have defined the problem let’s go ahead and talk about its solutions.
Find Intersection and Union of Two Linked Lists – Solution I
[adinserter block=”2″]Union
A simple and straightforward solution is to traverse the first linked list and add all its elements to the result list. Then, iterate over the second list, and for each node, check if there is a node with the same value in the result list (or the first list). If such a node exists, then ignore it. Otherwise, add a new node with the current node’s value to the result list.
Intersection
Similar to the union approach, iterate over the first linked list. Now here for each node, we check if there is a node with the same data in the second linked list. If this is the case, we insert a new node with the current node’s value to the resulting linked list.
Implementation
The implementation of this approach is given below:
# node for the linked list class Node: def __init__(self, value=None, next=None): self.value = value self.next = next # reference to the next node # implementation of linked list class LinkedList: def __init__(self): self.head = None self.length = 0 # total number of elements in the linked list # adds a node at the start of the linked list def insert(self, value): node = Node(value, self.head) # create a node self.head = node self.length = 1 # increment the length # traverse the complete list and print each node's value def displayList(ll): temp = ll while temp: print(temp.value, end="\t") temp = temp.next print("") # check if a node with the given value exists in the linked list def itemExists(ll, value): temp = ll # iterate through the list while temp: if temp.value == value: # element is found return True temp = temp.next return False def union(ll1, ll2): result = LinkedList() # create a new linked list # iterate over the first linked list and add its elements in the result list temp = ll1 while temp: result.insert(temp.value) temp = temp.next # iterate over the 2nd linked list and add those elements in the result list that are not in result already temp = ll2 while temp: if not itemExists(result.head, temp.value): result.insert(temp.value) temp = temp.next return result.head def intersection(ll1, ll2): result = LinkedList() # create a new linked list # iterate over the first linked list temp = ll1 while temp: if itemExists( ll2, temp.value ): # if the current node's value exists in the second linked list, then add it to the result list result.insert(temp.value) temp = temp.next return result.head # create linked list 1 ll1 = LinkedList() ll1.insert(2) ll1.insert(6) ll1.insert(4) ll1.insert(3) # create linked list 2 ll2 = LinkedList() ll2.insert(11) ll2.insert(3) ll2.insert(2) union_ll = union(ll1.head, ll2.head) intersection_ll = intersection(ll1.head, ll2.head) print("Linked list 1") displayList(ll1.head) print("Linked list 2") displayList(ll2.head) print("Union of linked list 1 and 2") displayList(union_ll) print("Intersection of linked list 1 and 2") displayList(intersection_ll)
Output
Linked list 1 3 4 6 2 Linked list 2 2 3 11 Union of linked list 1 and 2 11 2 6 4 3 Intersection of linked list 1 and 2 2 3
This approach is simple but is not efficient. We get a time complexity of O(m*n)
in both cases. Here, m
and n
are the lengths of the first and second linked lists, respectively.
We can find a solution that is more efficient than this approach. Let’s discuss it.
Find Intersection and Union of Two Linked Lists – Solution II
[adinserter block=”2″]The idea behind this method is to use hash tables to keep track of the items visited instead of checking every time whether that item exists in the other list or not.
Union
First, we iterate over the linked list one and add its elements in the result list just like we did in the above solution. However, we also store the current node’s value as a key in a hash table. Then, we iterate over the second list. For each node’s value, we check if it is in the hash table. If it is, we don’t add it to the result list. Otherwise, we do.
Intersection
We traverse the first linked list and add its elements as keys in the hash table. Then, we iterate over the second linked list and check if the current node’s value is in the hash table. If it is, we insert it in the result list.
Implementation
# traverse the complete list and print each node's value def displayList(ll): temp = ll while temp: print(temp.value, end="\t") temp = temp.next print("") def union(ll1, ll2): dictt = {} result = LinkedList() # iterate over the first linked list and add its elements in the result list and in the dictionary/hash table temp = ll1 while temp: result.insert(temp.value) dictt[temp.value] = 1 temp = temp.next # iterate over the second linked list and add those elements in the result list that are not in the dictionary/hash table temp = ll2 while temp: if ( dictt.get(temp.value, None) == None ): # this method returns None if there is no key with temp.value. Otherwise, returns its value result.insert(temp.value) temp = temp.next return result.head def intersection(ll1, ll2): dictt = {} result = LinkedList() # iterate over the first linked list and add its elements in the dictionary/hash table temp = ll1 while temp: dictt[temp.value] = 1 temp = temp.next # iterate over the second linked list and add those elements in the result list that are in the dictionary/hash table temp = ll2 while temp: if dictt.get( temp.value, None ): # this method returns None if there is no key with temp.value. Otherwise, returns its value result.insert(temp.value) temp = temp.next return result.head # create linked list 1 ll1 = LinkedList() ll1.insert(2) ll1.insert(6) ll1.insert(4) ll1.insert(3) # create linked list 2 ll2 = LinkedList() ll2.insert(11) ll2.insert(3) ll2.insert(2) union_ll = union(ll1.head, ll2.head) intersection_ll = intersection(ll1.head, ll2.head) print("Linked list 1") displayList(ll1.head) print("Linked list 2") displayList(ll2.head) print("Union of linked list 1 and 2") displayList(union_ll) print("Intersection of linked list 1 and 2") displayList(intersection_ll)
Output
Linked list 1 3 4 6 2 Linked list 2 2 3 11 Union of linked list 1 and 2 11 2 6 4 3 Intersection of linked list 1 and 2 3 2
The time complexity of this approach is O(m+n)
.