Write a program to find the node at which the intersection of two singly linked lists begins.

For example, the following two linked lists:

[LeetCode] 160. Intersection of Two Linked Lists_linked list

begin to intersect at node c1.

Example 1:

[LeetCode] 160. Intersection of Two Linked Lists_链表_02

Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
Output: Reference of the node with value = 8
Input Explanation: The intersected node's value is 8 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,6,1,8,4,5]. There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B.

Example 2:

[LeetCode] 160. Intersection of Two Linked Lists_java_03

Input: intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
Output: Reference of the node with value = 2
Input Explanation: The intersected node's value is 2 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [1,9,1,2,4]. From the head of B, it reads as [3,2,4]. There are 3 nodes before the intersected node in A; There are 1 node before the intersected node in B.

Example 3:

[LeetCode] 160. Intersection of Two Linked Lists_leetcode_04

Input: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
Output: null
Input Explanation: From the head of A, it reads as [2,6,4]. From the head of B, it reads as [1,5]. Since the two lists do not intersect, intersectVal must be 0, while skipA and skipB can be arbitrary values.
Explanation: The two lists do not intersect, so return null.

Notes:

  • If the two linked lists have no intersection at all, return null.
  • The linked lists must retain their original structure after the function returns.
  • You may assume there are no cycles anywhere in the entire linked structure.
  • Each value on each linked list is in the range [1, 10^9].
  • Your code should preferably run in O(n) time and use only O(1) memory.

相交链表。

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

两种思路,一个是需要求出两个链表各自的长度,当两者不想等的时候,需要先遍历长的链表,使得其剩下的长度要跟短的链表长度相等,再去找两者的交点。如图所示就是需要先让B移动到node.value = 0的那个节点,再遍历A和B,看看交点在哪里。

时间O(n)

空间O(1)

JavaScript实现

 1 /**
 2  * @param {ListNode} headA
 3  * @param {ListNode} headB
 4  * @return {ListNode}
 5  */
 6 var getIntersectionNode = function(headA, headB) {
 7     // corner case
 8     if (headA === null || headB === null) {
 9         return null;
10     }
11 
12     // normal case
13     let lenA = len(headA);
14     let lenB = len(headB);
15     if (lenA > lenB) {
16         while (lenA !== lenB) {
17             headA = headA.next;
18             lenA--;
19         }
20     } else {
21         while (lenA !== lenB) {
22             headB = headB.next;
23             lenB--;
24         }
25     }
26     while (headA !== headB) {
27         headA = headA.next;
28         headB = headB.next;
29     }
30     return headA;
31 };
32 
33 var len = function(head) {
34     let res = 1;
35     while (head !== null) {
36         res++;
37         head = head.next;
38     }
39     return res;
40 }

 

Java实现

 1 public class Solution {
 2     public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
 3         // corner case
 4         if (headA == null || headB == null) {
 5             return null;
 6         }
 7 
 8         // normal case
 9         int lenA = len(headA);
10         int lenB = len(headB);
11         if (lenA > lenB) {
12             while (lenA != lenB) {
13                 headA = headA.next;
14                 lenA--;
15             }
16         } else {
17             while (lenA != lenB) {
18                 headB = headB.next;
19                 lenB--;
20             }
21         }
22         while (headA != headB) {
23             headA = headA.next;
24             headB = headB.next;
25         }
26         return headA;
27     }
28 
29     private int len(ListNode head) {
30         int len = 1;
31         while (head != null) {
32             head = head.next;
33             len++;
34         }
35         return len;
36     }
37 }

 

另外一种思路是不求两个链表的长度,分别遍历A和B。如果按照此例,遍历完A和B的时候并不能找到两者的交点,此时可以将A的末尾接上B(A+B),或者将B的末尾接上A(B+A),这样保证了两者遍历的长度相等,就一定能找到交点。这个例子给的不是特别好,因为遍历的时候,程序很可能在8之前的那个1的node就退出循环了。但是如果这个节点不相等,程序会在8的地方退出。

A: 4 - 1 - 8 - 4 - 5 - 5 - 0 - 1 - 8 - 4 - 5

B: 5 - 0 - 1 - 8 - 4 - 5 - 4 - 1 - 8 - 4 - 5

时间O(m + n), A和B的长度和

空间O(1)

JavaScript实现

 1 /**
 2  * @param {ListNode} headA
 3  * @param {ListNode} headB
 4  * @return {ListNode}
 5  */
 6 var getIntersectionNode = function(headA, headB) {
 7     // corner case
 8     if (headA === null || headB === null) {
 9         return null;;
10     }
11 
12     // normal case
13     let a = headA;
14     let b = headB;
15     while (a !== b) {
16         a = a === null ? headB : a.next;
17         b = b === null ? headA : b.next;
18     }
19     return a;
20 };

 

Java实现

 1 /**
 2  * Definition for singly-linked list.
 3  * public class ListNode {
 4  *     int val;
 5  *     ListNode next;
 6  *     ListNode(int x) {
 7  *         val = x;
 8  *         next = null;
 9  *     }
10  * }
11  */
12 public class Solution {
13     public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
14         if (headA == null || headB == null) return null;
15         ListNode a = headA;
16         ListNode b = headB;
17         while (a != b) {
18             a = a == null ? headB : a.next;
19             b = b == null ? headA : b.next;
20         }
21         return a;
22     }
23 }

 

LeetCode 题目总结