zoukankan      html  css  js  c++  java
  • [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. 

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

    求两个链表的交点,要求Time: O(n), Space: O(1)

    解法1:交点最早可能出现在短链表的第一个节点,后面的节点两个链表一样。所以,长链表的比短链表开始多出的那些就没用。求出两个链表的长度差值,把较长的链表向后移动这个差值,变成一样长。然后在一个一个的比较。

    解法2: 双指针,用两个指针pA和pB分别指向链表A和B。然后让它们分别遍历整个链表,每步一个节点。当pA到达链表末尾时,让它指向B的头节点(没错,是B);类似的当pB到达链表末尾时,重新指向A的头节点。如果pA在某一点与pB相遇,则pA/pB就是交集开始的节点。

    Java: Solution 1

    public class Solution {
        public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
            if (headA == null || headB == null) return null;
            int lenA = getLength(headA), lenB = getLength(headB);
            if (lenA > lenB) {
                for (int i = 0; i < lenA - lenB; ++i) headA = headA.next;
            } else {
                for (int i = 0; i < lenB - lenA; ++i) headB = headB.next;
            }
            while (headA != null && headB != null && headA != headB) {
                headA = headA.next;
                headB = headB.next;
            }
            return (headA != null && headB != null) ? headA : null;
        }
        public int getLength(ListNode head) {
            int cnt = 0;
            while (head != null) {
                ++cnt;
                head = head.next;
            }
            return cnt;
        }
    }
    

    Java: Solution 2

    public class Solution {
        public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
            if (headA == null || headB == null) return null;
            ListNode a = headA, b = headB;
            while (a != b) {
                a = (a != null) ? a.next : headB;
                b = (b != null) ? b.next : headA;
            }
            return a;
        }
    } 

    Python:

    class Solution:
        # @param two ListNodes
        # @return the intersected ListNode
        def getIntersectionNode(self, headA, headB):
            if headA is None or headB is None:
                return None
    
            pa = headA # 2 pointers
            pb = headB
    
            while pa is not pb:
                # if either pointer hits the end, switch head and continue the second traversal, 
                # if not hit the end, just move on to next
                pa = headB if pa is None else pa.next
                pb = headA if pb is None else pb.next
    
            return pa # 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
    

    Python: wo

    class Solution(object):
        def getIntersectionNode(self, headA, headB):
            if not headA or not headB:
                return None
    
            a, b = headA, headB
            while a != b:
                a = a.next if a else headB
                b = b.next if b else headA
                
            return a  

    Python: Solution 1

    class Solution(object):
        def getIntersectionNode(self, headA, headB):
            lenA = self.getListLen(headA)
            lenB = self.getListLen(headB)
            if lenA > lenB:
                for i in range(lenA - lenB):
                    headA = headA.next
            elif lenA < lenB:
                for i in range(lenB - lenA):
                    headB = headB.next
            while headA != headB:
                headA, headB = headA.next, headB.next
            return headA
    
        def getListLen(self, head):
            length = 0
            while head:
                length += 1
                head = head.next
            return length 

    Python: Solution 2

    class ListNode:
        def __init__(self, x):
            self.val = x
            self.next = None
    
    class Solution:
        # @param two ListNodes
        # @return the intersected ListNode
        def getIntersectionNode(self, headA, headB):
            curA, curB = headA, headB
            begin, tailA, tailB = None, None, None
            
            # a->c->b->c
            # b->c->a->c
            while curA and curB:
                if curA == curB:
                    begin = curA
                    break
                    
                if curA.next:
                    curA = curA.next
                elif tailA is None:
                    tailA = curA
                    curA = headB
                else:
                    break
                
                if curB.next:
                    curB = curB.next
                elif tailB is None:
                    tailB = curB
                    curB = headA
                else:
                    break
            
            return begin  

    C++:

    class Solution {
    public:
        ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
            if (!headA || !headB) return NULL;
            int lenA = getLength(headA), lenB = getLength(headB);
            if (lenA < lenB) {
                for (int i = 0; i < lenB - lenA; ++i) headB = headB->next;
            } else {
                for (int i = 0; i < lenA - lenB; ++i) headA = headA->next;
            }
            while (headA && headB && headA != headB) {
                headA = headA->next;
                headB = headB->next;
            }
            return (headA && headB) ? headA : NULL;
        }
        int getLength(ListNode* head) {
            int cnt = 0;
            while (head) {
                ++cnt;
                head = head->next;
            }
            return cnt;
        }
    };
    

    C++:

    class Solution {
    public:
        ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
            if (!headA || !headB) return NULL;
            ListNode *a = headA, *b = headB;
            while (a != b) {
                a = a ? a->next : headB;
                b = b ? b->next : headA;
            }
            return a;
        }
    };
    

     

    类似题目:

    [LeetCode] 349. Intersection of Two Arrays 两个数组相交

    [LeetCode] 350. Intersection of Two Arrays II 两个数组相交II 

       

    All LeetCode Questions List 题目汇总

  • 相关阅读:
    php极光网络一键登录(yii框架)
    Sublime Text3将多行转为为一行 | Sublime Text 快速分别独立选中多行
    mysql 将时间戳转换成日期格式
    Vant主题定制修改颜色样式
    TypeError: this.getOptions is not a function 引入less一直报错
    export defaul 和 export定义和区别
    Vue vant引入,tabbar封装使用示例
    php去除富文本编辑器中的内容格式
    ES6:高级数组函数,filter/map/reduce
    [BZOJ2793][Poi2012]Vouchers
  • 原文地址:https://www.cnblogs.com/lightwindy/p/8606877.html
Copyright © 2011-2022 走看看