单链表---相交链表

struct ListNode 
{
	int val;
	struct ListNode* next;
};
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB);

方法一---长链表先走长度差,两者同步遍历到相交结点

两个单链表,判断是否相交,若相交返回相交结点,不相交返回NULL。

如果相交,由于结点的next指针只能指向一个结点,那么两个链表在相交后的结点就都是相同结点

那么如果两个链表相交,他们的尾结点一定相同,因此我们通过遍历得到的尾结点是否相同来判断两个链表是否相交。对于相交结点的返回,我们观察可以知道,两个链表的长度差,如果我们让长链表走长度差的步数,两个链表再以相同速度一同遍历,那么当遍历到结点相同时,就得到了相交结点,这就是本题的大致思路。

首先,如果两个链表其中有一个为NULL,那么就不存在相交结点,然后我们分别遍历两个链表拿到尾结点,通过尾结点是否相同来判断两者是否相交。相交则计算长度差,然后两次移动,第一次长链表移动长度差,第二次两个链表一起移动直到结点相同停止。

        if((headA==NULL) || (headB==NULL))
            return NULL;
        struct ListNode* curA = headA;
        struct ListNode* curB = headB;
        int A = 1;
        int B = 1;

遍历得到尾结点顺便计算两个链表的长度:

        while(curA->next)
        {
            curA= curA->next;
            A++;
        }
        while(curB->next)
        {
            curB = curB->next;
            B++;
        }

判断尾结点是否相同,不相同返回NULL:

        if(curA != curB)
            return NULL;

相同我们创建一个变量n接收一下长度差的绝对值,使用假设判断法创建一个Longlist和Shortlist,先把headA赋给Longlist,headB赋给Shortlist,通过if判断,如果A<B,将headB赋给Longlist,headA赋给Shortlist:

        int n =abs(A-B);
        struct ListNode* Longlist = headA , *Shortlist = headB;
        if(A<B)
        {
            Longlist = headB;
            Shortlist = headA;
        }

那么我们先让长链表Longlist走n步,然后让Longlist和Shortlist同步走直到两者相同即相交结点:

        while(n--)
        {
            Longlist=Longlist->next;
        }
        while(Longlist!=Shortlist)
        {
            Longlist=Longlist->next;
            Shortlist=Shortlist->next;
        }
        return Longlist;//Shortlist

整体代码如下:

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
        if((headA==NULL) || (headB==NULL))
            return NULL;
        struct ListNode* curA = headA;
        struct ListNode* curB = headB;
        int A = 0;
        int B = 0;
        while(curA->next)
        {
            curA= curA->next;
            A++;
        }
        while(curB->next)
        {
            curB = curB->next;
            B++;
        }
        if(curA != curB)
            return NULL;
        
        int n =abs(A-B);
        struct ListNode* Longlist = headA , *Shortlist = headB;
        if(A<B)
        {
            Longlist = headB;
            Shortlist = headA;
        }
        while(n--)
        {
            Longlist=Longlist->next;
        }
        while(Longlist!=Shortlist)
        {
            Longlist=Longlist->next;
            Shortlist=Shortlist->next;
        }
        return Longlist;//Shortlist
}

方法二---暴力遍历,嵌套循环

我们遍历链表A,在每次遍历的时候将结点与每个链表B的结点进行对比,相同则为相交结点,返回;不同则继续遍历。如果出了嵌套循环,那么就返回NULL。不做过多阐述。

//方法二:暴力遍历
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB)
{
	struct ListNode* cur1 = headA;
	while (cur1)
	{
		struct ListNode* cur2 = headB;
		while (cur2)
		{
			if (cur1 == cur2)
				return cur2;
			cur2 = cur2->next;
		}
		cur1 = cur1->next;
	}
	return NULL;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值