算法【链表】 | 【链表尾部重合问题】

一、链表尾部重合

1、步骤

> 首先判断是否有环:【若有环,则返回入环结点】
	方法1:可使用set容器,每次将链表结点压入时,进行查询;
	方法2:使用快慢指针【快指针走两步,慢指针走一步】若走不到空结点,则有环。
			且当两个指针相遇时,快指针回到头节点,两个指针每次走一步,当两个指针相遇时,
			就是入环结点;
> 若链表无环:	
	两条无环链表,先进行长度判断。在将长的链表的前面多余部分去除,在与另一个链表进行循环
	判断。
> 若链表有环且入环结点相等:
	则重复上述无环操作;
> 若链表有环且入环结点不相等:
	 则让其中一个链表的入环结点开始循环,是否能遇到另一条入环结点,若可以则返回其中一个
	 即可,否则返回null

在这里插入图片描述

2、代码分块

2.1 数据结构

在这里插入图片描述

2.2 获取入环结点

在这里插入图片描述

2.3无环链表处理

在这里插入图片描述

2.4 有环链表处理

在这里插入图片描述

3、代码

/*----------------------------------------------------------------------
	> File Name: intersect.cpp
	> Author: Jxiepc
	> Mail: Jxiepc
	> Created Time: Fri 04 Feb 2022 08:20:21 PM CST
----------------------------------------------------------------------*/

/**
 * 判断两个链表是否有相交
 * 2) 两条无环链表;
 * 1)两个有环链表若相交返回第一个相交结点;
 * 2)
 * */

#include <iostream>


typedef struct linkNode {
    int val;
    struct linkNode *next;

    /* 重载!=运算符 */
    bool operator!= (struct linkNode *node) {
        if(this->val != node->val || node->next != this->next)
            return true;
        return false;
    }

    /* 重载==运算符 */
    bool operator==(struct linkNode *node) {
        if(this->val != node->val || node->next != this->next)
            return false;
        return true;
        
    }
}LinkNode;


/** 判断是否有环,找到入环第一个环结点,若无环,则返回null */
LinkNode* getLoopNode(LinkNode *head) {
    if(head == nullptr || head->next == nullptr || head->next->next == nullptr)
        return nullptr;

    /* 慢指针每次走一步 */
    LinkNode *n1 = head->next;
    /* 快指针每次走两步 */
    LinkNode *n2 = head->next->next;

    /* 当两个指针相遇时,则快指针返回头节点,继续每次走一步后,相遇时则为入环结点 */
    while(n1 != n2) {
        if(n2->next == nullptr || n2->next->next == nullptr) 
            return nullptr;
        n2 = n2->next->next;
        n1 = n1->next;
    }

    /* 快指针继续返回头结点 */
    n2 = head;
    /* 当在次相遇则为入环结点 */
    while(n1 != n2) {
        n1 = n1->next;
        n2 = n2->next;
    }

    return n1;
} 


/** 链表无环,返回第一个相交结点 */
LinkNode* noLoop(LinkNode *head1, LinkNode *head2) {
    if(head1 == nullptr || head2 == nullptr)
        return nullptr;
    LinkNode *cur1 = head1;
    LinkNode *cur2 = head2;

    int n = 0;
    /** 判断两个链表的长度 */
    while(cur1->next != nullptr) {
        n++;
        cur1 = cur1->next;
    }

    while(cur2->next != nullptr) {
        n--;
        cur2 = cur2->next;
    }

    if(cur1 != cur2) {
        return nullptr;
    }

    /** 从定位链表长短 */
    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;
}


/** 两个有环链表,返回第一个相交结点 */
LinkNode* bothLoop(LinkNode *head1, LinkNode *loop1, LinkNode *head2, LinkNode *loop2) {
    LinkNode *cur1 = nullptr;
    LinkNode *cur2 = nullptr;
    
    /* 判断入环结点是否相等 */
    if(loop1 == loop2) {
        cur1 = head1;
        cur2 = head2;
        int n=0;
        /* 循环的到入环结点结束 */
        while(cur1 != loop1) {
            n++;
            cur1 = cur1->next;
        }
        
        /* 循环的到入环结点结束 */
        while(cur2 != loop2) {
            n--;
            cur2 = cur2->next;
        }
        /* 重新赋值head */
        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;
    } else {
        cur1 = loop1->next;
        while(cur1 != loop1) {
            if(cur1 == loop2) 
                return loop1;
            cur1 = cur1->next;
        } 
        return nullptr;
    }
}

LinkNode* getIntersectNode(LinkNode *head1, LinkNode *head2) {
    if(head1 == nullptr || head2 == nullptr)
        return nullptr;
    LinkNode *loop1 = getLoopNode(head1);
    LinkNode *loop2 = getLoopNode(head2);
    if(loop1 == nullptr && loop2 == nullptr)
        return noLoop(head1, head2);
    if(loop1 != nullptr && loop2 != nullptr)
        return bothLoop(head1, loop1, head2, loop2);
    return nullptr;
}

int main(int argc, char* argv[])
{
    LinkNode *Node1 = new LinkNode[10];
    LinkNode *Node2 = new LinkNode[10];
    
    LinkNode n1, n2, n3, n4, n5, n6, n7, n8, n9, nn1, nn2, nn3;
    n1.val = 10;
    n2.val = 3;
    n3.val = 5;
    n4.val = 2;
    n5.val = 8;
    n6.val = 7;
    n7.val = 6;
    n8.val = 9;
    n9.val = 1;
    nn1.val = 11;
    nn2.val = 23;
    nn3.val = 12;

    /* 链表1 */
    Node1->next = &n1;
    n1.next = &n2;
    n2.next = &n3;
    n3.next = &n4;
    n4.next = &n5;
    n5.next = &n6;
    n6.next = &n7;
    n7.next = &n8;
    n8.next = &n9;
    n9.next = nullptr;
    
    /* 链表2 */
    Node2->next = &nn1;
    nn1.next = &nn2;
    nn2.next = &nn3;
    nn3.next = &n4;
    /* 打印链表 */
    LinkNode *tmp1 = new LinkNode;
    tmp1 = Node1;
    while(tmp1->next != nullptr) {
        tmp1 = tmp1->next;
        std::cout << tmp1->val << " ";
    }
    std::cout << std::endl;

    LinkNode *tmp2 = new LinkNode;
    tmp2 = Node2;
    while(tmp2->next != nullptr) {
        tmp2 = tmp2->next;
        std::cout << tmp2->val << " ";
    }
    std::cout << std::endl;

    LinkNode *ret = new LinkNode;
    ret = getIntersectNode(Node1, Node2);
    std::cout << ret->val << std::endl; 
    return 0;
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jxiepc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值