Это сумасшедшее решение, которое я нашел во время кодирования поздно ночью, оно в 2 раза медленнее принятого ответа, но использует хороший арифметический взлом:
public ListNode findIntersection(ListNode a, ListNode b) {
if (a == null || b == null)
return null;
int A = a.count();
int B = b.count();
ListNode reversedB = b.reverse();
// L = a elements + 1 c element + b elements
int L = a.count();
// restore b
reversedB.reverse();
// A = a + c
// B = b + c
// L = a + b + 1
int cIndex = ((A+B) - (L-1)) / 2;
return a.atIndex(A - cIndex);
}
Мы разделяем списки на три части: a
это часть первого списка до начала общей части, b
это часть второго списка до общей части и c
, которая является общей частью двух списки. Мы посчитаем размеры списка, а затем перевернем список b
, это приведет к тому, что когда мы начнем обход списка с конца a
, мы закончим на reversedB
(мы пойдем a -> firstElementOfC -> reversedB
). Это даст нам три уравнения, которые позволят нам получить длину общей части c
.
Это слишком медленно для соревнований по программированию или использования в производстве, но я думаю, что этот подход интересен.