# 5 Best Ways to Find the First Common Element Between Two Linked Lists in Python

Rate this post

π‘ Problem Formulation: Given two singly linked lists, the objective is to find the first common element between them. For instance, if the first linked list is `1 -> 2 -> 3 -> 4` and the second is `6 -> 3 -> 4`, the desired output is `3`, as it is the first element that appears in both lists.

## Method 1: Hash Table Approach

This approach entails traversing the first linked list and storing each element in a hash table (a `set` in Python). Then, we traverse the second linked list and check each element against the hash table. The first match is the first common element. This method offers O(m+n) time complexity, where m and n are the lengths of the linked lists.

Here’s an example:

```class Node:
def __init__(self, value):
self.value = value
self.next = None

def common_element_hash_table(list1, list2):
seen = set()
while list1:
list1 = list1.next
while list2:
if list2.value in seen:
return list2.value
list2 = list2.next
return None

# Example usage

```

Output:

`3`

In this code snippet, we declare a `Node` class for our linked list, then define a function `common_element_hash_table()` that takes two linked lists. We iterate over the first list adding each element to a `set`, then iterate over the second list to find the first common element. Finally, we call the function with two linked lists and print the result.

## Method 2: Brute Force

The brute force method involves comparing each node of the first linked list with each node of the second linked list until a common element is found. This approach has a time complexity of O(m*n), making it less efficient for long lists.

Here’s an example:

```def common_element_brute_force(list1, list2):
while list1 is not None:
current = list2
while current is not None:
if list1.value == current.value:
return list1.value
current = current.next
list1 = list1.next
return None

# Example usage
# (Assuming the same Node class and linked lists from the previous example)
```

Output:

`3`

This function, `common_element_brute_force()`, straightforwardly compares each element of the first list with each element of the second list using two nested loops, returning the first common value found or `None` if no commonality exists.

## Method 3: Two Pointers Approach

The two pointers approach is efficient when both linked lists are sorted. Pointers start at the heads of their respective lists, advancing independently until a common element is found, boasting a time complexity of O(m+n).

Here’s an example:

```def common_element_two_pointers(list1, list2):
while list1 and list2:
if list1.value == list2.value:
return list1.value
elif list1.value < list2.value:
list1 = list1.next
else:
list2 = list2.next
return None

# Example usage
# (Assuming the same Node class and linked lists from the previous examples)
```

Output:

`3`

The `common_element_two_pointers()` function uses two pointers, which move through both lists. When a common element is found, or one of the list ends, the search stops. If a common element is found, it is returned; otherwise, `None` is returned.

## Method 4: Recursive Approach

A recursive solution relies on the call stack to compare the nodes of the two linked lists. Note that recursion may lead to a stack overflow on very large lists. This method is also O(m+n).

Here’s an example:

```def common_element_recursive(list1, list2):
if list1 is None or list2 is None:
return None
if list1.value == list2.value:
return list1.value
return common_element_recursive(list1.next, list2) or common_element_recursive(list1, list2.next)

# Example usage
# (Assuming the same Node class and linked lists from the previous examples)
```

Output:

`3`

The `common_element_recursive()` function works by comparing the current nodes of both lists and then moving to the next node of either one or both lists when necessary. The recursion continues until a common element is found or one list runs out of nodes.

## Bonus One-Liner Method 5: Using List Comprehension with Hashing

This one-liner is a concise way to combine list comprehension with hashing. It converts one linked list to a `set` and then iterates over the second linked list, producing a list of common elements.

Here’s an example:

```common_element_one_liner = lambda list1, list2: next((node.value for node in list2 if node.value in set(node.value for node in list1)), None)
# Example usage
```

Output:

`3`

This one-liner defines a lambda function that takes two lists. It creates a set from the first list and then uses list comprehension to search for the first element in the second list that is also in the set. It returns the first common element found, or `None` if there is no match.

## Summary/Discussion

• Method 1: Hash Table Approach. Strengths: Efficient with O(m+n) complexity and simpler to understand. Weaknesses: Requires additional memory for the hash table.
• Method 2: Brute Force. Strengths: Simple to implement and understand. Weaknesses: Least efficient with O(m*n) complexity, not suitable for large lists.
• Method 3: Two Pointers Approach. Strengths: Efficient with sorted lists. Weaknesses: Inapplicable if lists are not sorted.
• Method 4: Recursive Approach. Strengths: Elegant recursive solution. Weaknesses: Risk of stack overflow with very large lists.
• Bonus Method 5: One-Liner with List Comprehension. Strengths: Extremely concise. Weaknesses: Potentially less readable and does not inherently work with data structures other than lists.