单链表(面试算法题3)---两链表相交问题

简介: 单链表(面试算法题3)---两链表相交问题

单链表往期文章:

单链表(面试算法题1)---学习链表的关键在于code

单链表(算法面试题2)---单链表进阶2 一题多解,逐步优化

单链表(面试算法题2)---单链表进阶1之快慢指针

问题描述:

       给定两个可能有环也有可能无环的单链表,头节点head1和head2

       请实现一个函数如果两个链表相交,请返回相交的第一个节点

       如果不相交,返回NULL。

解题思路:

       1.判断两链表有没有环

               通过快慢指针进行判断,如果有环,则两个指针一定会相遇,否则无环。

      2.什么样的两个单链表才会相交

               两个链表的组合可能性:

               1).两个链表均无环---->有可能相交

               2).两个链表均有环---->也可能相交

               3).一个有环一个无环--->不可相交(如果相交则一定共用一个环或者共用最后一个节点)

       3.无环链表相交问题

               1)判断两个无环链表是否相交。只需要考虑他们是否共用了最后一个节点即可,

                          如果共用则相交,否则一定不相交。

               2)找到相交的节点,并返回

                   ==》通过两个链表的长度来找。如果链表A与链表B相交,len(A)>len(B)

                           那么我们可以知道A比B长len(A)-len(B),不妨让指向A的指针先走len(A)-len(B)的                              长度,再让指向A和指向B的指针同时走,当pA==pB时,到达交点。

       4.有环链表相交问题

               1)判断两个有环链表是否相交。

                       如果相交,则有两种情况:

                       情况1:在环外相交(包括在入环节点处相交)--->那么他们一定共用一个入环节点。

                       情况2:在环内相交--->可以让一个指针追另外一个指针,如果能相遇则相交        

                       否则,不相交,返回NULL

   代码如下:

               

//通过快慢指针,如果有环,则最后一定会相遇
//有环-->则返回第一个入环节点
//无环-->返回NULL
Node getLoopNode(Node head){
    //如果为空链表或着只有一个节点或者两个节点则不可能有环
    if(head == NULL || head->next == NULL || head->next->next == NULL){
        return NULL;
    }
    //slow  fast
    Node slow = head->next;
    Node fast = head->next->next;
    while(slow != head){
        if(head->next == NULL || head->next->next == NULL){
            return NULL;
        }
        slow = slow->next;
        fast = fast->next->next; 
    }
    //找到入环节点-->把快指针指向头部,重新开始,
    //当慢指针与快指针再次相遇时,相遇点一定是入环的第一个节点
    fast = head;
    while(fast != slow){
        fast = fast->next->next;
        slow = slow->next;
    }
    return slow;
}
//如果两个链表的无环,返回第一个相交点,如果不相交,返回NULL
Node noLoop(Node head1,Node head2){
    if(head1 == NULL || head2 == NULL){
        return NULL;
    }
    //如果相交,则最后一定共用最后一个节点
    int n = 0;
    Node cur1 = head1;
    Node cur2 = head2;
    while(cur1->next != NULL){
        n++;
        cur1 = cur1->next;
    }
    while(cur2->next != NULL){
        n--;
        cur2 = cur2->next;
    }
    if(cur1 != cur2)//如果没有共用一个最后一个节点,则一定不相交
    {
        return NULL;
    }
    cur1 = n > 0 ? head1:head2;
    cur2 = cur1==head1 ? head2:head1;
    n = abs(n);
    while(n != 0){
        n--;
        cur1 = cur1->next;
    }
    while(cur1 != cur2){
        cur1 = cur1->next;
        cur2 = cur2->next;
    }
    return cur1;
}
//两个有环链表
/*
*   1.不相交   2.在环外相交(一定共用一个入环节点)  2.在环内相交
*/
Node bothLoop(Node head1,Node loop1,Node head2,Node loop2){
    Node cur1 = NULL;
    Node cur2 = NULL;
    if(loop1 == loop2){ //在环外相交或者在入环处相交
        int n = 0;
        cur1 = head1;
        cur2 = head2;
        while(cur1 != loop2){
            n++;
            cur1 = cur1->next;
        }
        while (cur2 != loop2)
        {
            n--;
            cur2 = cur2->next;
        }
        if(cur1 != cur2){
            return NULL;
        }
        cur1 = n>0 ? head1:head2; 
        cur2 = cur1==head1 ? head2:head1;
        while(n != 0){
            n--;
            cur1 = cur1->next;
        }
        while(cur1 != cur2){
            cur1 = cur1->next;
            cur2 = cur2->next;
        }
        return cur1;
    }else{
        //如果是相交在环内,让一个指针区追另一个
        cur1 = loop1;
        while(cur1 != loop1){
            if(cur1 == loop2){
                return cur1;
            }
            cur1 = cur1->next;
        }
        return NULL;
    }
}
Node getIntersectNode(Node head1,Node head2){
    if(head1 == NULL || head2 == NULL){
        return NULL;
    }
    Node loop1 = getLoopNode(head1);
    Node loop2 = getLoopNode(head2);
    //两个链表如果相交的话,一定是两个都无环或者两个都有环
    /*因为有环相交的环,他们一定有一个共用的环*/
    if(loop1 == NULL && loop2 == NULL){
        //无环
        return noLoop(head1,head2);
    }
    if(loop1 != NULL && loop2 != NULL){
        //有环
    }
    return NULL;
}
相关文章
|
15天前
|
算法
【优选算法专栏】专题九:链表--------两两交换链表中的节点
【优选算法专栏】专题九:链表--------两两交换链表中的节点
17 0
|
1月前
|
存储
【单链表】数据结构单链表的实现
【单链表】数据结构单链表的实现
|
1月前
|
算法
【数据结构与算法】题解 | #反转链表#
【数据结构与算法】题解 | #反转链表#
|
15天前
|
算法
算法系列--递归(一)--与链表有关(上)
算法系列--递归(一)--与链表有关
27 0
|
15天前
|
算法
算法系列--链表刷题(二)(下)
算法系列--链表刷题(二)(下)
16 0
|
24天前
|
缓存 算法 搜索推荐
【数据结构】链表(单链表与双链表实现+原理+源码)
【数据结构】链表(单链表与双链表实现+原理+源码)
|
1月前
|
算法
LeetCode刷题---160. 相交链表(双指针-对撞指针)
LeetCode刷题---160. 相交链表(双指针-对撞指针)
|
1月前
|
算法 Java 索引
[Java·算法·简单] LeetCode 141. 环形链表 详细解读
[Java·算法·简单] LeetCode 141. 环形链表 详细解读
23 0
|
1月前
|
算法
常见算法题—707.设计链表
【2月更文挑战第10天】
34 7
|
29天前
|
Java 程序员
java线程池讲解面试
java线程池讲解面试
52 1