链表相关的热点面试题(二)

本文详细探讨了链表相交问题的解决方法,包括判断相交及找到交点,同时也深入研究了复杂链表的复制问题,提供了解决方案并附有示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相关题目:
1.判断两个链表是否相交, 若相交, 求交点。 ( 假设链表不带环)
2.判断两个链表是否相交, 若相交, 求交点。 ( 假设链表可能带环) 【升级版】
3.复杂链表的复制。 一个链表的每个节点, 有一个指向next指针指向下一个节点, 还有一个random指针指向这个链表中的一个随机
节点或者NULL, 现在要求实现复制这个链表, 返回复制后的新链表。
4.求两个已排序单链表中相同的数据。 void UnionSet(Node* l1, Node* l2);

  • 问题1:判断两个链表是否相交, 若相交, 求交点。( 假设不带环)
    1)判断是否相交
    首先我们来想想链表相交的几种情况
    这里写图片描述
    无非就这两种情况,我们发现只要相交,那么两个链表的尾节点必定是一个。所以我们只需要遍历一遍链表,然后判断尾节点是否相等就可以。当然这是不带环的。
bool IsIntersect(Node<int>* head1, Node<int>* head2)
{
    if (head1 == NULL || NULL == head2)
        return false;
    Node<int>* p1 = head1;
    Node<int>* p2 = head2;
    while (p1->_next)
    {
        p1 = p1->_next;
    }
    while (p2->_next)
    {
        p2 = p2->_next;
    }
    return p1 == p2;
}

2)求交点
1.先分别遍历一遍两条链表,求出两链表各自的节点个数len1和len2。
2.让节点多的链表先走|len1-len2|
3.两条链表同时向后步进,并判断节点是否相同。第一个相同点就是第一个交点。
![这里写图片描述](https://img-blog.youkuaiyun.com/20170515203628521?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzQzMTIzODY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

Node<int>*  EnterCross(Node<int>* head1, Node<int>* head2)
{
    assert(head1&&head2);
    Node<int>* cur = head1;
    int len1 = 0;
    while (cur)
    {
        cur = cur->_next;
        ++len1;
    }
    cur = head2;
    int len2 = 0;
    while (cur)
    {
        cur = cur->_next;
        ++len2;
    }
    Node<int>* p1 = head1;
    Node<int>* p2 = head2;
    int count =len1 > len2 ? len1 - len2 : len2 - len1;

    if (len1 > len2)
        while (count--)
            p1 = p1->_next;
    else
        while (count--)
            p2 = p2->_next;

    while (p1 != p2)
    {
        p1=p1->_next;
        p2 =p2->_next;
    }
    return p1;
}
  • 问题2:判断两个链表是否相交, 若相交, 求交点。(假设链表可能带环) 【升级版】
    1)判断是否相交
    如果都带环,则快慢指针判断是否会相交,如果死循环,则不想交。
    如果都不带环则直接调用上一题的代码。
    其他情况没有可能相交。
bool TwoLoopIsIntersect(Node<int>* head1, Node<int>* head2)
{
    if (IsExitsLoop(head1).second &&IsExitsLoop(head2).second)
    {
        Node<int>* fast = head1;
        Node<int>* slow = head2;
        //如果没有相交,那么将会死循环
        while (fast != slow)
        {
            fast = fast->_next->_next;
            slow = slow->_next;
        }
        return true;
    }
    else if (!IsExitsLoop(head1).second&&!IsExitsLoop(head2).second)
    {
        return IsIntersect(head1, head2);
    }
    else 
        return false;
}

2)求交点
首先我们来看看相交有几种情况
这里写图片描述
第一种,我们可以看到整个环都是交点,我们可以转换成求任意链表环入口点,然后就等得到环内个节点。
第二种,可以转换成求不带环的相交链表求交点,我们可以求两链表各自环入口点,然后求出各链表到环入口点距离,然后就转换成问题1第一问。

  • **问题3:复杂链表的复制。 一个链表的每个节点, 有一个指向next指针指向下一个节点, 还有一个random指针指向这个链表中的一个随机
    节点或者NULL, 现在要求实现复制这个链表, 返回复制后的新链表。**

复杂链表复制,其实就是在原链表上创建节点,然后再将链表分离出来。

RandomListNode *copyRandomList(RandomListNode *head) {
        // write your code here
        if(head==NULL)
            return NULL;
        RandomListNode* cur=head,*newnode=NULL;
        //插入新链表
        while(cur)
        {
            newnode=new RandomListNode(cur->label);
            newnode->next=cur->next;
            cur->next=newnode;
            cur=newnode->next;
        }
        //复制random
        cur=head;
        while(cur)
        {
            newnode=cur->next;
            if(cur->random)
                newnode->random=cur->random->next;
            cur=newnode->next;
        }
        //分离链表
        RandomListNode* dest=head->next;
        cur=head;
        while(cur)
        {
            newnode=cur->next;
            cur->next=newnode->next;
            cur=newnode->next;
            if(cur)
                newnode->next=cur->next;
        }
        return dest;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值