链表与环--「链表带环问题」

本文详细介绍了链表带环问题的解决方法,包括如何判断单链表是否带环及确定环入口点,还探讨了链表相交问题,并提供了一个复杂链表复制的示例。

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

链表 与 环

「链表带环问题」是经典面试考点。总结解法如下

1 判断单链表是否带环

Key:
快慢指针法。使用两个指针指向头节点,一个指针每次遍历两个结点(快指针),另一个指针每次遍历一个结点。当快慢指针相遇,则链表带环(不带环时 遇到空指针break)。

证明:带环链表快慢指针一定相遇。
快指针每次走两步,两步分开看:第一步与 慢指针的一步走完后在圆内相对位置不变,则快慢指针 的遍历过程可看作「慢指针不动,快指针每次走一步」
则两者必定相遇。

2 判断入口点

这里写图片描述
设快慢指针相遇于 a 点,其他参数见图示。
易知 快指针的移动距离为慢指针的两倍, 则有

2(L1+right)=L1+right+kL22∗(L1+right)=L1+right+k∗L2

化简可得
L1=left+k1L2L1=left+(k−1)∗L2

由上式可知:
从起点遍历到入口点的长度 等于 从a点逆时针遍历n圈的距离 + 从a点逆时针走到入口点的距离
即:
一指针从起点开始遍历,另一指针从a点开始逆时针遍历,必定相遇于入口点。

3 链表相交问题

不带环

key:
若两链表相交,则链表最后一个点相同。

可通过栈的结构找到相交点
或遍历两链表a、b的长度,以 a 大于 b 为例,使用一个指针先走b-a步,再同时开始走,相遇点为交点。

带环

环在 交点后,同不带环问题

交点在 环中,视作交点在环的入口点

4 复杂链表的复制

//#define _CRT_SECURE_NO_WARNINGS
#define N 100
#include<iostream>
#include<assert.h>
using namespace std;

typedef struct ComplexNode
{
    int _data; // 数据 
    struct ComplexNode * _next; // 指向下一个节点的指针 
    struct ComplexNode * _random; // 指向随机节点(可以是链表中的任意节点 or 空) 
}cNode;

cNode* initNode(int data)
{
    cNode* tempNode = (cNode*)malloc(sizeof(cNode));
    tempNode->_data = data;
    tempNode->_next = NULL;
    tempNode->_random = NULL;
    return tempNode;
}
cNode* initNode(cNode& lastNode)
{
    cNode* tempNode = (cNode*)malloc(sizeof(cNode));
    tempNode->_data = lastNode._data;
    tempNode->_next = lastNode._next;
    tempNode->_random = NULL;
    return tempNode;
}

cNode* copyList(cNode* head)
{
    assert(head);
    cNode* nowNode = head;
    while (nowNode)
    {
        cNode* tempNode = initNode(*nowNode);
    }

}

int main()
{

    getchar();
    getchar();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值