编写一个程序,找到两个单链表相交的起始节点。
题目链接:https://leetcode-cn.com/problems/intersection-of-two-linked-lists/
相交链表解题思路详解:https://blog.youkuaiyun.com/dawn_after_dark/article/details/73864643
C代码:双指针(每个指针都遍历了AB两个链表)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
/*
*定义两个指针, 第一轮让两个到达末尾的节点指向另一个链表的头部, 最后如果相遇则为交点(在第一轮移动中恰好抹除了长度差)
*两个指针等于移动了相同的距离, 有交点就返回, 无交点就是各走了两条指针的长度
*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if( headA==NULL || headB==NULL )
return NULL;
struct ListNode *pA = headA, *pB = headB;
// 在这里第一轮体现在pA和pB第一次到达尾部会移向另一链表的表头,
//而第二轮体现在如果pA或pB相交就返回交点, 不相交最后就是null==null
while( pA != pB )
{
pA = pA==NULL ? headB : pA->next;
pB = pB==NULL ? headA : pB->next;
}
return pA;
}
C代码:双指针 [B链表变环,验证A链表是否有环。若有环,由于快指针追上了慢指针,此时将慢指针指向A链表的头节点,使得slow和fast指针与交点距离相同,齐头并进(slow==fast)即可找出交点]
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
//看不懂就结合leedcode的图走一遍
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if( headA==NULL || headB==NULL )
return NULL;
struct ListNode *last = headB;
while( last->next != NULL )
last = last->next;
last->next = headB;
struct ListNode *slow=headA, *fast=headA; //注意此时的slow和fast必须从同一起点开始
while( fast!=NULL && fast->next!=NULL ) //链表还没遍历完
{
slow = slow->next;
fast = fast->next->next;
if( slow == fast ) //fast指针追上slow指针,故有环
{
slow = headA; //此时消除了slow,fast之间距离差距,使得slow,fast与交点距离相同
while( slow != fast ) //slow==fast时,指向相交点
{
slow = slow->next;
fast = fast->next;
}
last->next = NULL;
return fast;
}
} //退出while循环,说明无环,则两链表不相交
last->next = NULL;
return NULL;
}
C代码:双指针(长链表的长度减去短链表的长度,得到相差的长度,之后让长链表从头结点开始走过这个长度,与短链表同时向后走,若指针相等,则链表相交;若走到NULL,则链表不相交)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode *pA = headA, *pB = headB;;
struct ListNode *tmp = NULL;
int lenght_A = 0 ,lenght_B = 0;
while( pA != NULL ) //计算链表A,B的长度
{
pA = pA->next;
lenght_A++;
}
while( pB != NULL )
{
pB = pB->next;
lenght_B++;
}
//使pA,pB分别指向距离A,B链表的尾结点相同的结点
pA = headA;
pB = headB;
if (lenght_A > lenght_B) {
int gap = lenght_A - lenght_B;
while( gap-- )
pA = pA->next;
} else {
int gap = lenght_B - lenght_A;
while( gap-- )
pB = pB->next;
}
//遍历找出相交结点
while ( pA && pB )
{
if( pA ==pB )
{
return pA;
}
pA = pA->next;
pB = pB->next;
}
return NULL;
}
注:若题目改为验证两个链表是否相交,则可以变换思路为使B链表的尾结点指针指向该链表的头节点,然后使用快慢指针的方法验证A链表是否有环。若有,则A,B链表相交,否则不相交
缺点:修改了原链表结构
C代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
bool getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if( headA==NULL || headB==NULL )
return false;
struct ListNode *last = headB;
while( last->next != NULL )
last = last->next;
last->next = headB;
struct ListNode *slow=headA, *fast=headA->next;
while( fast!=NULL && fast->next!=NULL ) //链表还没遍历完
{
slow = slow->next;
fast = fast->next->next;
if( slow == fast ) //fast指针追上slow指针,故有环
return true;
}
return false;
}