leetcode题解-160. 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:

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.

本题是寻找两个链表的交叉点。可以想象,公共部分一定是从后开始向前遍历寻找最方便,但是链表只可以单向。那么我们就会想两个链表以一个公共部分在最后,然后不同的部分在前面,所以第一种思路就是暴力嵌套循环==不推荐因为会超时,代码入下:

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode A=headA, B=headB;
        while(A != null){
            while(B != null){
                if(A == B)
                    return A;
                else
                    B = B.next;
            }
            B = headB;
            A = A.next;
        }
        return null;
    }

接下来我们会怎么想,如果两个链表长度相同,那么可以每次都移动两个链表的元素直到二者相同,这种方法是效果最好的。首先获得两个链表的长度,然后把较长的那个前面一部分截断,最后同时向后遍历两个链表直到找到相同部分,代码入下:

    public ListNode getIntersectionNode1(ListNode headA, ListNode headB) {
        int lenA=0, lenB=0;
        ListNode A=headA, B=headB;
        while(A != null){
            lenA ++;
            A = A.next;
        }

        while(B != null) {
            lenB++;
            B = B.next;
        }
        A = headA;
        B=headB;

        while(lenA > lenB){
            A = A.next;
            lenA --;
        }
        while(lenA < lenB){
            B = B.next;
            lenB --;
        }

        while(A != B){
            A = A.next;
            B = B.next;
        }

        return A;
    }

最后一种方法比较巧妙,就是利用了链表无环这个限定条件,即便两个链表长度不同,但是同时使用两个指针分别跑完两个链表,总是会在交叉点相遇,也就是说第一个指针跑了x+n+y,第二个指针跑了y+n+x,然后二者相遇。代码入下:

    public ListNode getIntersectionNode2(ListNode headA, ListNode headB) {
        //boundary check
        if(headA == null || headB == null) return null;

        ListNode a = headA;
        ListNode b = headB;

        //if a & b have different len, then we will stop the loop after second iteration
        while( a != b){
            //for the end of first iteration, we just reset the pointer to the head of another linkedlist
            a = a == null? headB : a.next;
            b = b == null? headA : b.next;
        }

        return a;
    }

但是理论上讲,这种方法只需要遍历不到两遍链表,而上面那种方法会遍历更多次链表,但不知道为什么这种方法效果会更差==

你可能感兴趣的:(leetcode刷题)