30+链表问题(一):如何判断链表是否成环?
作者:互联网
引子
在上一篇文章《30+链表问题:概览》的引言中,我提到了当初在校招时遇到的一道链表面试题。就是这道题了。下面是问题描述以及解决方案。
问题描述
给定一个链表,如何判断该链表是否成环?
解题思路
首先,一听到这个问题,脑子一下子映出下面这幅链表成环的图:
如图,上面就是一个已经成环的链表。标红的是头结点。
针对这个问题,我的解决方案是:
使用两个指针 slow、fast 遍历该链表,slow每次走一步,fast走两步(实际上,只需要两个指针一快一慢即可)。如果 fast 指针 走到头,那说明链表中不存在环。否则,两个指针在无尽的旅程中一定会相遇。
为了说明白这个情况:我还专门做了动态图(实际上,为了做这个动态图,我还花30大洋买了个软件。。。。):
代码实现
这里,LinkedList是我自己定义的链表类、Node是我自己定义的结点类。源码请参考附件,或《30+链表问题:概览》。
/**
* 判断一个链表是否成环
*
* @param list 链表
* @return true Or false
*/
private boolean isContainCircle(LinkedList list) {
// 两个指针,刚开始都指向 头结点
Node slow = list.getHead();
Node fast = list.getHead();
// 如果链表成环,则直到量指针相遇之前,该循环将一直进行;
while (fast != null && fast.getNext() != null) {
/* fast 每次走两步,slow 走一步;
* 在 fast 为null 之前,slow一定不为 null */
slow = slow.getNext();
fast = fast.getNext().getNext();
// 这里直接比较其地址即可
if (slow == fast) {
return true;
}
}
return false;
}
我们写代码测试一下:
public static void main(String[] args) {
Main runner = new Main();
LinkedList list = runner.buildLinkedListWithCircle();
boolean containCircle = runner.isContainCircle(list);
System.out.println("该链表是否包含环:" + containCircle);
}
/**
* 构建出示例中的包含环的链表
*
* @return 包含环的链表
*/
private LinkedList buildLinkedListWithCircle() {
LinkedList list = new LinkedList();
Node nodeOf2 = null;
for (int i = 1; i <= 7; i++) {
Node node = new Node(String.valueOf(i) + i);
list.add(node);
if (i == 2) {
nodeOf2 = node;
}
}
list.add(nodeOf2);
return list;
}
上面构建出的链表即上面我给的图片中的链表。我们执行这段代码,得到的结果如下:
该链表是否包含环:true
如果我们备注掉 buildLinkedListWithCircle 方法中的 list.add(nodeOf2); 这一行代码,再执行,得到结果:
该链表是否包含环:false
总结
在处理链表问题的时候,双指针、多指针是常见的结题方式。这种问题见得多了,感觉都是套路。
文中代码作者只是为了做个演示,有的细节并没有做严格校验。目前没有发现有严重的错误,如果有发现问题的朋友,欢迎指出哦~希望和大家一起进步~
源码附件
源代码:https://download.csdn.net/download/zereao/11705715
GitHub:https://github.com/Zereao/LinkListInterviewQuestion/tree/master/LinkedListContainCircle
参考文章
标签:slow,LinkedList,30,list,fast,链表,成环,指针 来源: https://blog.csdn.net/Zereao/article/details/100576173