C# 判断一个单链表是否有环及环长和环的入口点
1.为什么写这个随笔?
前几天参加一个电面,被问到这个问题,想总结一下。
2.为什么标题强调C#?
想在网上看看代码,却没找到C#版的,于是自己用C#实现一下。
一、解决问题的思路
1.一种比较耗空间的做法是,从头开始遍历链表,把每次访问到的结点存入一个集合(hashset)或字典(dictionary),如果发现某个结点已经被访问过了,就表示这个链表存在环,并且这个结点就是环的入口点。
空间复杂度为O(n),时间复杂度为O(n)
2.追赶法:使用两个slow, fast指针从头开始扫描链表。指针slow 每次走1步,指针fast每次走2步。如果存在环,则指针slow、fast会相遇;如果不存在环,指针fast遇到NULL退出。
空间复杂度为O(1),时间复杂度为O(n)
仅仅考虑代码实现方面第一种方法相对简单,所以下面用第二种方法来实现。
二、解析(追击相遇)
给出一个存在环的单链表:1,2,3,4,5,3,4,5...
用图表示出来:

然后按照追赶法的定义一步一步走:

从上图可以看出第四次和第七次快慢指针在节点4处相遇,7-4=3,正好是环的长度;
求出环的长度后,我们便可以求出入口点:
链表总长=5;
头结点到入口点的距离=链表总长-环长;即=5-3=2;
然后从头结点开始向下遍历,得到入口点3;
三、代码
1.单链表节点
//单链表节点
class LinkNode<T>
{
public LinkNode<T> Next
{ get; set; }
public T Data
{ get; set; }
public LinkNode()
{
Data = default(T);
Next = null;
}
public LinkNode(T val)
{
Data = val;
Next = null;
}
public LinkNode(T val,LinkNode<T> node)
{
Data = val;
Next = node;
}
}
2.单链表
class DLinkedList<T>
{
public LinkNode<T> Head
{ get; set; }
public int Length
{ get; set; }
public DLinkedList()
{
Length = ;
Head = null;
}
public void Add(LinkNode<T> node)//插入节点
{
if (IsEmpty())
{
Head = node;
Length++;
return;
}
else
{
LinkNode<T> currentNode = Head;
while (currentNode.Next != null)
{
currentNode = currentNode.Next;
}
currentNode.Next = node;
Length++;
}
}
public void Display()//显示链表
{
LinkNode<T> currentNode = Head;
while (currentNode != null)
{
Console.WriteLine(currentNode.Data);
currentNode = currentNode.Next;
}
}
public int GetLength()//获取链表长度
{
return Length;
}
public bool IsEmpty()//判空
{
return Head == null ? true : false;
}
public bool HasCircle()//判断是否有环
{
LinkNode<T> slowNode = Head;
LinkNode<T> fastNode = Head;//定义快慢节点,开始指向头结点
bool result = false;
int count = ;
int step = ;
while (slowNode.Next != null && fastNode.Next.Next != null)
{
try
{
slowNode = slowNode.Next;//慢节点指向下一个
fastNode = fastNode.Next.Next;//快节点指向下一个节点的下一个节点
}
catch (NullReferenceException)
{
result = false;
break;
}
if (slowNode == fastNode && slowNode != Head && slowNode != null)
{
result = true;
Console.WriteLine($"The currentNode's Data is {slowNode.Data}");
count++;
}
if (count == )//第一次相遇
step++;//计步,获取环长
if (count == )//第二次相遇
{
Console.WriteLine($"Circle's length is {step}");
break;
}
}
GetPoint(step);
return result;
}
public LinkNode<T> GetPoint(int circleLength)//获取相交点
{
int lineLength = Length -circleLength;
int num = ;
LinkNode<T> currentNode = Head;
while(currentNode.Next!=null)
{
currentNode = currentNode.Next;
num++;
if(num==lineLength)
{
break;
}
}
Console.WriteLine($"The meet node's Data is {currentNode.Data}");
return currentNode;
}
}
3.测试
class Program
{
static void Main(string[] args)
{
DLinkedList<int> list = new DLinkedList<int>();
LinkNode<int> tmp=null;
for(int i =;i<=;i++)
{
LinkNode<int> node = new LinkNode<int>(i);
if (i == )
tmp = node;
list.Add(node);
}
list.Add(tmp);
Console.WriteLine(list.HasCircle());
Console.ReadKey();
}
}
测试结果如图:

C# 判断一个单链表是否有环及环长和环的入口点的更多相关文章
- LeetCode 笔记系列六 Reverse Nodes in k-Group [学习如何逆转一个单链表]
题目:Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. ...
- C语言一个单链表的实现
-- 所谓链表记住一句即可:地址不连续,大家只是握个手而已: list0.c #include<stdio.h> #include<malloc.h> typedef int ...
- java单链表的实现自己动手写一个单链表
单链表:单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素.链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是 ...
- c语言,递归翻转一个单链表,c实现单链表
目的:主要是练习c里面单链表的实现,递归思想复习; #include <stdlib.h> #include <stdio.h> typedef struct _Node{// ...
- [二叉树算法]让树所有叶子节点连成一个单链表,让rchild作为 next指针
//让树所有叶子节点连成一个单链表,让rchild作为 next指针 LNode *head=null,*pre=null;//全局变量 LNode *InOrder(BTNode *T){ if(T ...
- java判断一个单向链表是否有环路
今天刷LeetCode刷到一道这样的题,详情参见(https://leetcode-cn.com/problems/linked-list-cycle/) ADT: class ListNode { ...
- php实现一个单链表
单链表,节点只有一个指针域的链表.节点包括数据域和指针域. 因此用面向对象的思维,节点类的属性就有两个:一个data(表示存储的数据),一个指针next(链表中指向下一个节点). 链表一个很重要的特性 ...
- 如何判断一个单向链表是否为回文链表(Palindrome Linked List)
题目:给定一个单向链表,判断它是不是回文链表(即从前往后读和从后往前读是一样的).原题见下图,还要求了O(n)的时间复杂度O(1)的空间复杂度. 我的思考: 1,一看到这个题目,大脑马上想到的解决方案 ...
- 008实现一个算法从一个单链表中返回倒数第n个元素(keep it up)
我们维护两个指针, 它们之间的距离为n. 然后.我将这两个指针同步地在这个单链表上移动,保持它们的距离 为n不变. 那么, 当第二个指针指到空时.第一个指针即为所求. #include <ios ...
随机推荐
- 2018 杭电多校1 - Distinct Values
题目链接 Problem Description Chiaki has an array of n positive integers. You are told some facts about t ...
- CF724E Goods transportation 最小割 DP
照惯例CF的题不放原题链接... 题意:一个序列上有n个点,每个点有权值pi和si.表示这个点一开始有pi个物品,最多可以卖出si个物品,每个点都可以把物品向编号更大的点运输,但是对于i < j ...
- Android 字母导航条实现
在Activity中进行功能的实现,需要用到第三方jar包:pinyin4j.jar,此jar包用于将汉字转换为汉语拼音. 首先,设置右侧边栏索引列表(A-Z),并且设置列表点击,Touch事件,点击 ...
- BZOJ4003:[JLOI2015]城池攻占——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4003 https://www.luogu.org/problemnew/show/P3261 小铭 ...
- BZOJ1053:[HAOI2007]反素数——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=1053 对于任何正整数x,其约数的个数记作g(x).例如g(1)=1.g(6)=4.如果某个正整数x满 ...
- codevs5037 线段树练习4加强版(暴力分块)
求大爷教线段树怎么写啊QAQ 只会写分块...一开始脑抽写成了O(NKlogN)还被CZL大爷嘲讽了一发T T f[i][j]表示在第i块中,模k为j的数有几个,然后每次修改的时候只需要打个标记,查询 ...
- cin.get()、流和缓冲区
大家好,这是我在CSDN的第一篇博客.我是一名学习GIS专业的大学生.我从小开始喜欢编程,可是到现在编程水平却长进不大,依然是菜鸟一个.究其原因,虽然这些年乱七八糟的东西学过不少,但是总的来说还是基础 ...
- 如何根据域名来得到对应的IP
如何根据域名来得到对应的IP呢? windows下打开cmd窗口,然后ping.如下图: 这样就可以看到IP了. 如何查看自己电脑对应的IP? 当通过代理上网时,可能无法通过网络连接信息查看自己电脑的 ...
- Axis2 WebService(配置、发布、调用)
准备工作 1.下载:axis2-1.5.4-bin.zip,axis2-1.5.4-war.zip 下载地址:http://axis.apache.org/axis2/java/core/ 2.环境变 ...
- 2015/9/1 Python基础(6):列表
列表和字符串类型很相似,是同样的序列式数据类型.但是字符串只能由字符组成,列表可以保留任意数目的Python对象的灵活的容器.Python的列表比C的数组要灵活,数组里面只能是一种类型,列表可以有多种 ...