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

    我还以为以后在不能免费做OJ的题了呢,想不到 OJ 又放出了不需要买书就能做的题,业界良心啊,哈哈^_^。这道求两个链表的交点题要求执行时间为 O(n),则不能利用类似冒泡法原理去暴力查找相同点,事实证明如果链表很长的话,那样的方法效率很低。我也想到会不会是像之前删除重复元素的题一样需要用两个指针来遍历,可是想了好久也没想出来怎么弄。无奈上网搜大神们的解法,发觉其实解法很简单,因为如果两个链长度相同的话,那么对应的一个个比下去就能找到,所以只需要把长链表变短即可。具体算法为:分别遍历两个链表,得到分别对应的长度。然后求长度的差值,把较长的那个链表向后移动这个差值的个数,然后一一比较即可。代码如下: 

    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;
        }
    };

    Java 解法一:

    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;
        }
    }

    这道题还有一种特别巧妙的方法,虽然题目中强调了链表中不存在环,但是我们可以用环的思想来做,我们让两条链表分别从各自的开头开始往后遍历,当其中一条遍历到末尾时,我们跳到另一个条链表的开头继续遍历。两个指针最终会相等,而且只有两种情况,一种情况是在交点处相遇,另一种情况是在各自的末尾的空节点处相等。为什么一定会相等呢,因为两个指针走过的路程相同,是两个链表的长度之和,所以一定会相等。这个思路真的很巧妙,而且更重要的是代码写起来特别的简洁,参见代码如下:

    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;
        }
    };

    Java 解法二:

    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;
        }
    }

    类似题目:

    Minimum Index Sum of Two Lists

    参考资料:

    https://leetcode.com/problems/intersection-of-two-linked-lists/

    https://leetcode.com/problems/intersection-of-two-linked-lists/discuss/49792/Concise-JAVA-solution-O(1)-memory-O(n)-time

    https://leetcode.com/problems/intersection-of-two-linked-lists/discuss/49785/Java-solution-without-knowing-the-difference-in-len!

    LeetCode All in One 题目讲解汇总(持续更新中...)

  • 相关阅读:
    开发和使用自定义服务器控件
    用户认证管理设计方案(转)
    用 @@ERROR 检测几条语句的成功
    在 ASP.NET 中支持数据库缓存相关性
    给新人程序员的八点建议(转)
    DataTable添加列
    各城市工资多少才等于北京5000元工资的生活?
    连续读取区块应用程序设置值
    VS2005 SP1发布,解决只能创建WebSite,无法创建Web Application项目的问题 (转)
    帮你免于失业的十大软件技术
  • 原文地址:https://www.cnblogs.com/grandyang/p/4128461.html
Copyright © 2011-2022 走看看