160.Intersection of Two Linked Lists
题意:
Write a program to find the node at which the intersection of two singly linked lists begins.
找出两条链表相交的第一个节点。
For example, the following two linked lists:
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
begin to intersect at node c1.
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.
- Your code should preferably run in O(n) time and use only O(1) memory.
class ListNode {
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
方法一:暴力破解 Time Limit Exceeded
- 时间复杂度 O(mn)
- 空间复杂度 O(1)
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null){
return null;
}
ListNode first = headA;
ListNode second = headB;
while(first != null){
while(second != null){
if(first == second){
return second;
}else{
second = second.next;
}
}
first = first.next;
second = headB;
}
return null;
}
方法二:使用HashSet,[Accepted]
- 时间复杂度: O(m+n)
- 空间复杂度: O(m)或者O(n)
public ListNode getIntersectionNode2(ListNode headA, ListNode headB) {
if(headA == null || headB == null){
return null;
}
HashSet<ListNode> list = new HashSet<>();
ListNode first = headA;
ListNode second = headB;
while(first != null){
list.add(first);
first = first.next;
}
while(second != null){
if(list.contains(second)){
return second;
}
second = second.next;
}
return null;
}
方法三:链表相遇问题
- 设两个指针,分别指向两条链表,
- 当链表A到达尾部时,下一个指向链表B的开头;
- 当链表B到达尾部时,下一个指向链表A的开头;
- 这样经过遍历两边链表,指针都会指向相同的结点,如果有相交点,最终就指向相交点,如果没有相交点,最终就都指向null。
时间复杂度: O(m+n)
空间复杂度:O(1)
public ListNode getIntersectionNode3(ListNode headA, ListNode headB) {
if(headA == null || headB == null){
return null;
}
ListNode first = headA;
ListNode second = headB;
while(first != second){
if(first == null){
first = headB;
}else{
first = first.next;
}
if(second == null){
second = headA;
}else{
second = second.next;
}
}
return first;
}
思路和上面的方法一样,只是写法更加简洁。
public ListNode getIntersectionNode4(ListNode headA, ListNode headB) {
// boundary check
if (headA == null || headB == null)
return null;
ListNode a = headA;
ListNode b = headB;
// if a & b have different len, then we will stop the loop after second
// iteration
while (a != b) {
// for the end of first iteration, we just reset the pointer to the
// head of another linkedlist
a = a == null ? headB : a.next;
b = b == null ? headA : b.next;
}
return a;
}
方法四:
如果两条链表的长度相等,那么就两个指针并行向后走;
如果两条链表长度不相等,那么就长的链表先向后走,直到两条链表长度相等,这时两条链表再一起向后走。
public ListNode getIntersectionNode5(ListNode headA, ListNode headB) {
int lenA = length(headA), lenB = length(headB);
// move headA and headB to the same start point
while (lenA > lenB) {
headA = headA.next;
lenA--;
}
while (lenA < lenB) {
headB = headB.next;
lenB--;
}
// find the intersection until end
while (headA != headB) {
headA = headA.next;
headB = headB.next;
}
return headA;
}
private int length(ListNode node) {
int length = 0;
while (node != null) {
node = node.next;
length++;
}
return length;
}