[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 ↘

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.
Credits:
Special thanks to @stellari for adding this problem and creating all test cases.

因为受上面一个问题影响Java单链表逆转所以我想着先逆转后求后面的子串,其实想多了,只要有一个公共的就当时后面的全部是公共。

解法一:
第一遍循环,找出两个链表的长度差N
第二遍循环,长链表先走N步,然后同时移动,判断是否有相同节点
解法一就相对简单粗暴,容易理解。

/** 
 * 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) {  
        if(headA==null || headB==null) return null;  

        ListNode p = headA;  
        ListNode q = headB;  
        int pcount = 0;  
        int qcount = 0;  
        while(p.next != null || q.next != null) {  
            if(p == q) return p;  
            if(p.next != null) p = p.next; else ++qcount;  
            if(q.next != null) q = q.next; else ++pcount;  
        }  
        if(p != q) return null;  
        p = headA;  
        q = headB;  
        while(pcount-- != 0) {  
            p = p.next;  
        }  

        while(qcount-- != 0) {  
            q = q.next;  
        }  

        while(p != q) {  
            p = p.next;  
            q = q.next;  
        }  
        return p;  
    }  
}  

解法二:
链表到尾部后,跳到另一个链表的头部, 另外一个链表的引用移到最后,此时跳过来的引用所在点就为第二个链表的开始点,然后再次一起遍历,相遇即为intersection points.

/** 
 * 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) {  
        if(headA==null || headB==null) return null;  

        ListNode p = headA;  
        ListNode q = headB;  
        if(p == q) return p;          
        while(p!=null && q!=null) {  
            p = p.next;  
            q = q.next;  
        }  

        if(p==null) p = headB; else q = headA;  

        while(p!=null && q!=null) {  
            p = p.next;  
            q = q.next;  
        }  

        if(p==null) p = headB; else q = headA;  

        while(p!=null && q!=null) {  
            if(p==q) return p;  
            p = p.next;  
            q = q.next;  
        }  
        return null;  
    }  
}  

就是先一起移动,如果一个到头了,就指向另一个的头,另一个到尾了,就说明这个指向的就是下次一起开始的地方。

解法三:
用两个引用,一个快一个慢,快的每次移动两个节点,当。。。。。。。。。。。我以为我理解了,其实没理解,然后去打断点调试就发现出问题了,不过leetcode上面显示Accept!很奇怪,先贴个代码,等以后问问别人。

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) {
            return null;
        }
        // get the tail of list A.
        ListNode node = headA;
        while (node.next != null) {
            node = node.next;
        }
        node.next = headB;
        ListNode result = listCycleII(headA);
        node.next = null;
        return result;
    }

    private ListNode listCycleII(ListNode head) {
        ListNode slow = head, fast = head.next;

        while (slow != fast) {
            if (fast == null || fast.next == null) {
                return null;
            }
            slow = slow.next;
            fast = fast.next.next;
        }
        slow = head;
        fast = fast.next;
        while (slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }
        return slow;
    }
目录
相关文章
|
存储 缓存 算法
LeetCode刷题---Two Sum(一)
LeetCode刷题---Two Sum(一)
Leetcode 4. Median of Two Sorted Arrays
题目描述很简单,就是找到两个有序数组合并后的中位数,要求时间复杂度O(log (m+n))。 如果不要去时间复杂度,很容易就想到了归并排序,归并排序的时间复杂度是O(m+n),空间复杂度也是O(m+n),不满足题目要求,其实我开始也不知道怎么做,后来看了别人的博客才知道有个二分法求两个有序数组中第k大数的方法。
41 0
|
存储 C++ Python
LeetCode刷题---Add Two Numbers(一)
LeetCode刷题---Add Two Numbers(一)
|
存储 算法 安全
LeetCode - #2 Add Two Numbers
我们社区从本期开始会将顾毅(Netflix 增长黑客,《iOS 面试之道》作者,ACE 职业健身教练。)的 Swift 算法题题解整理为文字版以方便大家学习与阅读。 不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。
LeetCode - #2 Add Two Numbers
|
存储 算法 安全
LeetCode - #1 Two Sum
我们社区从本期开始会将顾毅(Netflix 增长黑客,《iOS 面试之道》作者,ACE 职业健身教练。)的 Swift 算法题题解整理为文字版以方便大家学习与阅读。 不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。
LeetCode - #1 Two Sum
LeetCode 141. 环形链表 Linked List Cycle
LeetCode 141. 环形链表 Linked List Cycle
LeetCode 237. 删除链表中的节点 Delete Node in a Linked List
LeetCode 237. 删除链表中的节点 Delete Node in a Linked List
LeetCode Contest 178-1367. 二叉树中的列表 Linked List in Binary Tree
LeetCode Contest 178-1367. 二叉树中的列表 Linked List in Binary Tree
LeetCode 167 Two Sum II - Input array is sorted(输入已排序数组,求其中两个数的和等于给定的数)
给定一个有序数组和一个目标值 找出数组中两个成员,两者之和为目标值,并顺序输出
88 0
LeetCode 234. 回文链表 Palindrome Linked List
LeetCode 234. 回文链表 Palindrome Linked List