题目就是如何判断一个单链表是否有环,也就是没有一个节点的next=null,这就是有环单链表
例如:无环单链表 e1>e2>e3>e4>e5>null
有环单链表 e1>e2>e3>e4>e5>e3 这里的e5节点又指向了e3节点,这就形成了环形链表。
判断方法有多种,如下三种方法思路:
方法1》》》1秒内不停的取链表节点的next,能取到next=null,说明无环,不能取到空,说明有环。
缺点:不准确,性能也不好。
方法2》》》没经过一个节点,就存到set中,每到一个节点就取set查找是否存在时间复杂度O(n)空间复杂度O(n) 。
缺点:占用O(n)的空间复杂度。
方法3》》》快慢指针(龟兔赛跑)
快指针每次走两步
慢指针每次走一步判断:
如果是环,快慢肯定相遇,相遇只是时间问题,时间复杂度是O(n)。
就好像两个人围着操场跑圈,一直跑,跑的快的一定会追上跑的慢的,这个就好比小学的应用题,两个人同时起跑,一快一慢,快的跑一圈60秒,慢的跑一圈90秒,问两人过了多长时间相遇。
缺点:不是常规思维,一开始可能不太好理解
快慢指针代码:
package com.example.demo.test;
class Element {
String name;
Element next;
public Element(String name) {
this.name = name;
}
public void setNext(Element next) {
this.next = next;
}
}
public class ReverseLinkedList {
public static void main(String[] args) {
Element e1 = new Element("e1");
Element e2 = new Element("e2");
Element e3 = new Element("e3");
e1.setNext(e2);
e2.setNext(e3);
System.out.println("----反转前----");
Element self = e1;
while(self.next != null) {
System.out.println(self.name + "的next:" +self.next.name);
self = self.next;
}
reverseList(e1);
System.out.println("----反转后----");
Element self2 = e3;
while(self2.next != null) {
System.out.println(self2.name + "的next:" +self2.next.name);
self2 = self2.next;
}
}
public static void reverseList(Element head) {
Element self = head;
Element prev = null;
while(self != null) {
//这里只关注当前节点的前一个节点
//而不需要在这里即设置当前节点的前一节点,也设置当前节点的下一节点的指向,
//如果这样设置了,代码进入死循环,例如: self.next.next = self
//而是在每一次循环中处理当前节点的前一节点
Element next = self.next;//取出当前节点的next节点
self.next = prev;//反转指针,当前节点的next节点指向前一节点
prev = self;//更新前一节点指针,下次循环使用
self = next;//当当前节点指向下一节点,准备接入下一次循环,来处理第二个节点的反转
}
}
}
输出结果为:true,demo中设置的数据确实是环形的。