标签:
https://oj.leetcode.com/problems/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:
null
.解题思路:
将headA这个链表的节点全部加入一个set,再对headB这个链表的所有节点看在不在set里,返回第一个在的,或者返回null。
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { Set<ListNode> set = new HashSet<ListNode>(); while(headA != null){ set.add(headA); headA = headA.next; } while(headB != null){ if(set.contains(headB)){ return headB; } headB = headB.next; } return headB; } }
但是题目要求用O(n)的时间和O(1)的内存,上面的解法花了O(n)的时间和O(n)的内存。思考如何改进。
观察上图链表的结构,其实只要找出两个链表中较长的那个,较长的那个先往后移动m-n,然后两个节点再每次同时往后移动一个节点,直到它们相等。这样就可以了。这样的时间复杂度是O(3n)。
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { ListNode traverseA = headA; ListNode traverseB = headB; int lengthA = 0; int lengthB = 0; while(traverseA != null){ traverseA = traverseA.next; lengthA++; } while(traverseB != null){ traverseB = traverseB.next; lengthB++; } traverseA = headA; traverseB = headB; if(lengthA > lengthB){ while(lengthA != lengthB){ traverseA = traverseA.next; lengthA--; } }else{ while(lengthA != lengthB){ traverseB = traverseB.next; lengthB--; } } while(traverseA != traverseB){ traverseA = traverseA.next; traverseB = traverseB.next; } return traverseA; } }
官方的solution里给了另一种很tricky的解法,很不容易想到。
用两个节点分别从两个链表的开头,同时走,A到结尾后,从B的开始继续,同理,B到结尾后从A的开头继续。这样,在第二轮,他们必然会在交接的节点相遇。
如果A和B的最后一个节点不等,他们一定是没有交接点的。
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { if(headA == null || headB == null){ return null; } ListNode tailA = null; ListNode tailB = null; ListNode traverseA = headA; ListNode traverseB = headB; while(true){ if(traverseA == traverseB){ return traverseA; } if(traverseA.next == null){ tailA = traverseA; traverseA = headB; }else{ traverseA = traverseA.next; } if(traverseB.next == null){ tailB = traverseB; traverseB = headA; }else{ traverseB = traverseB.next; } //注意这个判断,光有tailA!=tailB是不行的,因为这是tailA可能已经到结尾了,而tailB还是null if(tailA!= null && tailB != null && tailA != tailB){ return null; } } } }
这个解法很巧妙,看下面的图
A: a1 → a2 ↘ c1 → c2 → c3 ↗ B: b1 → b2 → b3
我们令a1-a2=a,c1-c3=c,b1-b3=b
实际上就是a+c+b==b+c+a
Intersection of Two Linked Lists
标签:
原文地址:http://www.cnblogs.com/NickyYe/p/4316218.html