26.LeetCode之相交链表

编写一个程序,找到两个单链表相交的起始节点。

题目链接:https://leetcode-cn.com/problems/intersection-of-two-linked-lists/

相交链表解题思路详解:https://blog.csdn.net/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;
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值