学习编程 2018-03-20
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
.Credits:
Special thanks to@stellarifor adding this problem and creating all test cases.
求两个链表的交点,要求Time: O(n), Space: O(1)
解法1:交点最早可能出现在短链表的第一个节点,后面的节点两个链表一样。所以,长链表的比短链表开始多出的那些就没用。求出两个链表的长度差值,把较长的链表向后移动这个差值,变成一样长。然后在一个一个的比较。
解法2:虽然题中强调链表不存在环,但可以用环的思想来做,让两条链表分别从各自的开头开始往后遍历,当其中一条遍历到末尾时,跳到另一个条链表的开头继续遍历。两个指针最终会相等,而且只有两种情况,一种情况是在交点处相遇,另一种情况是在各自的末尾的空节点处相等。因为两个指针走过的路程相同,是两个链表的长度之和,所以一定会相等。
Java:
public class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { if (headA == null || headB == null) return null; int lenA = getLength(headA), lenB = getLength(headB); if (lenA > lenB) { for (int i = 0; i < lenA - lenB; ++i) headA = headA.next; } else { for (int i = 0; i < lenB - lenA; ++i) headB = headB.next; } while (headA != null && headB != null && headA != headB) { headA = headA.next; headB = headB.next; } return (headA != null && headB != null) ? headA : null; } public int getLength(ListNode head) { int cnt = 0; while (head != null) { ++cnt; head = head.next; } return cnt; } }
Java:
public class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { if (headA == null || headB == null) return null; ListNode a = headA, b = headB; while (a != b) { a = (a != null) ? a.next : headB; b = (b != null) ? b.next : headA; } return a; } }
Python:
class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: # @param two ListNodes # @return the intersected ListNode def getIntersectionNode(self, headA, headB): curA, curB = headA, headB begin, tailA, tailB = None, None, None # a->c->b->c # b->c->a->c while curA and curB: if curA == curB: begin = curA break if curA.next: curA = curA.next elif tailA is None: tailA = curA curA = headB else: break if curB.next: curB = curB.next elif tailB is None: tailB = curB curB = headA else: break return begin
C++:
class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { if (!headA || !headB) return NULL; int lenA = getLength(headA), lenB = getLength(headB); if (lenA < lenB) { for (int i = 0; i < lenB - lenA; ++i) headB = headB->next; } else { for (int i = 0; i < lenA - lenB; ++i) headA = headA->next; } while (headA && headB && headA != headB) { headA = headA->next; headB = headB->next; } return (headA && headB) ? headA : NULL; } int getLength(ListNode* head) { int cnt = 0; while (head) { ++cnt; head = head->next; } return cnt; } };
C++:
class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { if (!headA || !headB) return NULL; ListNode *a = headA, *b = headB; while (a != b) { a = a ? a->next : headB; b = b ? b->next : headA; } return a; } };