160. 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:

160. Intersection of Two Linked Lists_第1张图片

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.

Credits:Special thanks to @stellari for adding this problem and creating all test cases.

Solution

Two iterations with counting length

先遍历一遍,计算出两个list的长度。然后让长的链表的头指针多走几步,之后双指针一起走直到相遇(可能为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) {
        int l1 = getLength(headA);
        int l2 = getLength(headB);
        
        if (l1 < l2) {
            return getIntersectionNode(headB, headA);
        }
        // make sure l1 >= l1
        for (int i = l2; i < l1; ++i) {
            headA = headA.next;
        }
        
        while (headA != headB) {    // iterate until two list meet
            headA = headA.next;
            headB = headB.next;
        }
        
        return headA;
    }
    
    private int getLength(ListNode head) {
        int len = 0;
        
        while (head != null) {
            ++len;
            head = head.next;
        }
        
        return len;
    }
}

Two iterations without counting length

其实没有必要计算list length,只需要排除掉长度差距即可,可以在第一遍遍历时如果走到null则切换到另一个list head,这样两个指针就可以到同一个起跑线了。

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode p = headA;
        ListNode q = headB;

        while (p != q) {
            p = p != null ? p.next : headB;
            q = q != null ? q.next : headA;
        }
        
        return p;
    }
}

Follow-up: How to detect if two linked lists have intersection?

其实比原题目简单,因为只需要返回boolean即可,基本有下面几种做法:

  • 将ListA的所有节点存入HashSet中,然后遍历ListB,看是否有重合。
  • 两个链表如果相交,tail node一定相同。那么可以找到tailA和tailB,比较是否相等即可。

但是这里有一个坑。如果input list有环怎么办?这样就找不到tail了。这种情况下,需要结合HashSet + findTail两种做法,对于listB来说,find tail的同时查询HashSet中是否已经有该节点,如果有那么当前节点即为伪tail;否则将节点加入到HashSet中。

遍历listB时也要维护listB的HashSet,如果listB已经遍历一圈还没有遇到和listA的intersection,即为不相交。

你可能感兴趣的:(160. Intersection of Two Linked Lists)