两个链表的交叉

请写一个程序,找到两个单链表最开始的交叉节点。

 注意事项
  • 如果两个链表没有交叉,返回null
  • 在返回结果后,两个链表仍须保持原有的结构。
  • 可假定整个链表结构中没有循环。
样例

下列两个链表:

A:          a1 → a2
                   ↘
                     c1 → c2 → c3
                   ↗            
B:     b1 → b2 → b3

在节点 c1 开始交叉。

需满足 O( n ) 时间复杂度,且仅用 O( 1 ) 内存。


这里主要有两个思路:

方法一:

对于仅判断相交不相交的话:判断最后一个节点是否相同的办法并不慢,如果两个链表长度m,n 那么复杂度O(m+n),这是最优的复杂度

如何寻找交叉节点:指针p、q分别遍历链表a、b,假设q先到达NULL(即 假设a 比 b 长),此时从a的头发出一个指针t,当p到达NULL时,从b的头发出s,当s==t的时候即交点.

代码如下:


/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    /**
     * @param headA: the first list
     * @param headB: the second list
     * @return: a ListNode
     */
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        // write your code here
        ListNode *a = headA,*b = headB;
        if(a == NULL || b == NULL)return NULL;
        while(a->next !=NULL)a = a->next;
        while(b->next !=NULL)b = b->next;
        if(a!=b)return NULL;
        a = headA;
        b = headB;
        
        while(a!=NULL && b!=NULL){
            a = a->next;
            b = b->next;
        }
        ListNode *c = NULL;
        if(!a){
            c = headB;
            a = headA;
            while(b != NULL){
                b = b->next;
                c = c->next;
            }
            while(1){
                if(c == a)return a;
                c = c->next;
                a = a->next;
            }
        }
        else{
            c = headA;
            b = headB;
            while(a != NULL){
                a = a->next;
                c = c->next;
            }
            while(1){
                if(c == b)return b;
                c = c->next;
                b = b->next;
            }
        }
    }
};

方法二:可以将一个链表的尾节点指向另一个链表的头结点。如果交叉,那么这就形成了环,剩下的问题就是如何判断一个链表是否是环,同时要知道环的起始节点。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值