Метод 1: подход грубой силы
Подход грубой силы включает в себя сравнение каждого узла из первого связанного списка с каждым узлом из второго связанного списка. Временная сложность этого метода равна O(m x n), где m и n — длины связанных списков, что делает его неэффективным для больших списков.
def get_intersection_point(head1, head2):
current1 = head1
while current1:
current2 = head2
while current2:
if current1 == current2:
return current1
current2 = current2.next
current1 = current1.next
return None
Метод 2: хеширование
При этом подходе мы сохраняем ссылки на узлы из первого связанного списка в хеш-таблице. Затем мы просматриваем второй связанный список и проверяем, существует ли какая-либо ссылка на узел в хеш-таблице. Этот метод имеет временную сложность O(m + n), но требует дополнительного места для хеш-таблицы.
def get_intersection_point(head1, head2):
node_set = set()
current1 = head1
while current1:
node_set.add(current1)
current1 = current1.next
current2 = head2
while current2:
if current2 in node_set:
return current2
current2 = current2.next
return None
Метод 3: разница в длине
При этом подходе мы сначала вычисляем длины обоих связанных списков. Затем мы проходим по более длинному списку, пока длины обоих списков не станут равными. Наконец, мы сравниваем узлы обоих списков, пока не найдем точку пересечения. Этот метод имеет временную сложность O(m + n) и не требует дополнительного места.
def get_intersection_point(head1, head2):
len1 = get_length(head1)
len2 = get_length(head2)
if len1 > len2:
head1 = move_head(head1, len1 - len2)
else:
head2 = move_head(head2, len2 - len1)
while head1 and head2:
if head1 == head2:
return head1
head1 = head1.next
head2 = head2.next
return None
def get_length(head):
length = 0
current = head
while current:
length += 1
current = current.next
return length
def move_head(head, steps):
current = head
for _ in range(steps):
current = current.next
return current
Метод 4: два указателя
В этом подходе мы используем два указателя, по одному для каждого связанного списка. Мы проходим по обоим спискам одновременно, и если указатель достигает конца списка, мы перенаправляем его в начало другого списка. Таким образом, указатели в конечном итоге встретятся в точке пересечения или оба станут None, если пересечения нет. Этот метод имеет временную сложность O(m + n) и не требует дополнительного места.
def get_intersection_point(head1, head2):
ptr1 = head1
ptr2 = head2
while ptr1 != ptr2:
ptr1 = head2 if ptr1 is None else ptr1.next
ptr2 = head1 if ptr2 is None else ptr2.next
return ptr1
В этой статье мы рассмотрели несколько методов поиска точки пересечения двух связанных списков. Мы рассмотрели подход грубой силы, хеширование, разницу в длине и технику двухочковых. Каждый метод имеет свои преимущества и особенности, зависящие от таких факторов, как временная сложность и использование пространства. Понимая эти методы, вы сможете уверенно решать проблемы пересечения в связанных списках. Приятного кодирования!