【LeetCode-面试算法经典-Java实现】【160-Intersection of Two Linked Lists(单链表的交集)】

【160-Intersection of Two Linked Lists(单链表的交集)】


【LeetCode-面试算法经典-Java实现】【所有题目目录索引】

原题

  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.

题目大意

  找两个单链表的交集部分。
  如果没有交集返回null。
  函数操作后,单链表必须返回他们原来的结构。
  假定整个链表中没有环。
  函数必须在O(N)时间复杂度,O(1)空间复杂度以内完成。

解题思路

  先将其中一个链表的链头按到另一个链表的尾部,如果他们有交集则会构成一个环,题目等价于找链表中的环的起始结点。找到后将链表还原。

代码实现

结点类

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 ta; // 用于记录headA链表的尾结点
        ListNode ha = headA;

        // 第一步、找到headA的尾结点
        while (ha.next != null) {
            ha = ha.next;
        }

        ta = ha; // 记录链表headA的尾结点

        // 第二步、将headB接到ta后面
        ta.next = headB;

        // 第三步、判断是否存在环
        // 判断链表是否存在环,办法为:
        // 设置两个指针(fast, slow),初始值都指向头,slow每次前进一步,fast每次前进二步,
        // 如果链表存在环,则fast必定先进入环,而slow后进入环,两个指针必定相遇。
        // (当然,fast先行头到尾部为NULL,则为无环链表)程序如下:

        ListNode fast = headA; // 每次前进一步
        ListNode slow = headA; // 每次前进二步
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;

            if (fast == slow) { // 如果相遇了就退出来
                break;
            }
        }

        // 没有环的情况
        if (fast == null || fast.next == null) {
            ta.next = null; // 解开拼接好的链表
            return null;
        }



        // 有环的情况
        // 找到环的入口点
        // 当fast若与slow相遇时,slow肯定没有走遍历完链表,而fast已经在环内循环了n圈(1<=n)。
        // 假设slow走了s步,则fast走了2s步(fast步数还等于s 加上在环上多转的n圈),设环长为r,则:
        //
        // 2s = s + nr
        // s= nr
        //
        // 设整个链表长L,入口环与相遇点距离为x,起点到环入口点的距离为a。
        // a + x = nr
        // a + x = (n – 1)r +r = (n-1)r + L - a
        // a = (n-1)r + (L – a – x)
        //
        // (L – a – x)为相遇点到环入口点的距离,由此可知,从链表头到环入口点等于(n-1)循环内环+相遇点到环入口点,
        // 于是我们从链表头、与相遇点分别设一个指针,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。
        slow = headA;
        while (slow != fast) {
            fast = fast.next;
            slow = slow.next;
        }

        ta.next = null;
        return slow;
    }
}

评测结果

  点击图片,鼠标不释放,拖动一段位置,释放后在新的窗口中查看完整图片。

【LeetCode-面试算法经典-Java实现】【160-Intersection of Two Linked Lists(单链表的交集)】_第1张图片

特别说明

欢迎转载,转载请注明出处【http://blog.csdn.net/derrantcm/article/details/47855991】

你可能感兴趣的:(LeetCode,LeetCode)