160. Intersection of Two Linked Lists

https://leetcode.com/problems/intersection-of-two-linked-lists/#/description

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.

Sol 1:

The key point is to find the overlap node, and when node A is not equal to node B, advance them and when either of them reaches the end, switch the head and continue the second traversal. There are two ways to get out the while A != B list :1) They meet. 2) They both hit the end = None. 

(similar to the check loop in linked list) 

# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        if (not headA) or (not headB):
            return None
        
        if headA and headB:
            A = headA
            B = headB
            while A != B:
                 # if either pointer hits the end, switch head and continue the second traversal, 
                 # if not hit the end, just move on to next
                if A:
                    A = A.next 
                else:
                    A = headB
                    
                if B:
                    B = B.next
                else:
                    B = headA
            return A  # only 2 ways to get out of the loop, they meet or the both hit the end=None
            
# the idea is if you switch head, the possible difference between length would be countered. 
# On the second traversal, they either hit or miss. 
# if they meet, pa or pb would be the node we are looking for, 
# if they didn't meet, they will hit the end at the same iteration, pa == pb == None, return either one of them is the same,None

Sol 2:

Traverse list A and list B once to get the length of list A and list B. Then reset current nodes as headA an headB. Advance the pointer on the longer list. While current A is not equal to current B, advance both list A and list B pointer, and after the while loop, we find the intersection where current node A equals to current node B, then return current A.

O(n) time and O(1) space 

# Definition for singly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        
        curA = headA
        curB = headB
        lenA = 0
        lenB = 0
        while curA:
            lenA += 1
            curA = curA.next
        while curB:
            lenB += 1
            curB = curB.next
        curA = headA
        curB = headB
        if lenA > lenB:
            for i in range(lenA - lenB):
                curA = curA.next
        elif lenB > lenA:
            for i in range(lenB - lenA):
                curB = curB.next
        while curB != curA:
            curB = curB.next
            curA = curA.next
        return curA
                

Sol 3:

This problem could be considered as the derivation of linked list cycle.
Let say there are two linked lists named l1 and l2. And h1 and t1 are the head and last nodes of l1 respectively, and h2 is the head node of l2.

  1. Concat h1 and t1
  2. Check whether there exists a cycle of linked list l2.
  3. Find that intersection if 2 is a truth.

Before doing the above steps, there are two linked lists in the picture:
enter image description here

After step 1:
enter image description here

Then let's try to make the linked lists easier to understood.
enter image description here
Node 8 is what we want. We can use then solve it by finding the start node of the cycle like the problem "linked list cycle II"

def getIntersectionNode(self, headA, headB):
    """
    :type head1, head1: ListNode
    :rtype: ListNode
    """ 
    if not headA or not headB: return None
    
    p = headA
    while p.next:
        p = p.next
    mark = p
    #make a cycled list
    mark.next = headA
    
    rst = None
    p1 = headB
    p2 = headB
    while p1 and p2:
        p1 = p1.next
        p2 = p2.next
        if p2: p2 = p2.next
        if p1 == p2: break

    if p1 and p2 and p1 == p2:
        p1 = headB
        while p1 != p2:
            p1 = p1.next
            p2 = p2.next
        rst = p1

    #unmake the cycle
    mark.next = None

return rst
原文地址:https://www.cnblogs.com/prmlab/p/6991875.html