title: 数据结构之链表面试题汇总(三)判断单链表是否有环、取出环的起始点、得到有环链表中环的长度
date: 2016-08-18 9:14:00
categories: 数据结构
版权声明:本站采用开放的[知识共享署名-非商业性使用-相同方式共享 许可协议]进行许可
所有文章出现的代码,将会出现在我的github中,名字可以根据类全名来找,我在github中的文件夹也会加目录备注。
判断单链表是否有环
思路:
- 首先判断链表是否为空,为空抛异常
- 利用”双指针“方法:
- 一个指针每次移动一个节点,另外一个指针每次移动两个节点,如果第一个指针所对应的节点等于第二个指针所对应的节点,那么这个链表有环
- 在这里需要注意传入来链表的节点数
图解:
代码实现:
public static boolean hasLoopReturnBoolean(Node head) {
Node first = head;
Node second = head;
// if the head is null return exception
if (head == null || head.getNext() == null)
return false;
// move first on step backward and the second move twice at once
// if the condition of the judgement without the second.getNext()!=null
// when it reach the tail it will raise the NPE
while (second != null && second.getNext() != null) {
first = first.getNext();
second = second.getNext().getNext();
// if first=second return true
if (first == second)
return true;
}
// else false
return false;
}
测试代码:有环
public class ReverseLinkedListTest {
public static void main(String[] args) {
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
node1.setNext(node2);
node2.setNext(node3);
node3.setNext(node4);
node4.setNext(node5);
node5.setNext(node3);
System.out.println(HasLoop.hasLoopReturnBoolean(node1));
}
}
运行结果:
测试代码:无环:即把第五个节点的设置下一个节点的代码注释掉
public class ReverseLinkedListTest {
/**
* @param args
*/
public static void main(String[] args) {
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
node1.setNext(node2);
node2.setNext(node3);
node3.setNext(node4);
node4.setNext(node5);
// node5.setNext(node3);
System.out.println(HasLoop.hasLoopReturnBoolean(node1));
}
}
运行结果:
有环单链表中,得到环的起始点
思路:
可以借助上一题中判断是否有环的方法,在循环中判断first=second的时候,如果相等,直接返回first或者second即可。
代码实现:
public static Node hasLoopReturnNode(Node head) {
Node first = head;
Node second = head;
// if the head is null return exception
if (head == null || head.getNext() == null)
return null;
// move first on step backward and the second move twice at once
// if the condition of the judgement without the second.getNext()!=null
// when it reach the tail it will raise the NPE
while (second != null && second.getNext() != null) {
first = first.getNext();
second = second.getNext().getNext();
// if first=second return true
if (first == second)
return first;
}
// else without loop
return null;
}
测试代码:有环
public class ReverseLinkedListTest {
/**
* @param args
*/
public static void main(String[] args) {
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
node1.setNext(node2);
node2.setNext(node3);
node3.setNext(node4);
node4.setNext(node5);
node5.setNext(node3);
System.out.println(HasLoop.hasLoopReturnNode(node1).getRecord());
}
}
运行结果:
无环测试代码:
public class ReverseLinkedListTest {
/**
* @param args
*/
public static void main(String[] args) {
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
node1.setNext(node2);
node2.setNext(node3);
node3.setNext(node4);
node4.setNext(node5);
// node5.setNext(node3);
System.out.println(HasLoop.hasLoopReturnNode(node1).getRecord());
}
}
运行结果:
如果没有环,返回的是null,如果要读取里面的数据,就会抛空指针异常
得到有环链表中环的长度
思路:
- 继续继承判断链表是否有环的方法,只不过在判断的时候,把一个链表的头节点传到函数中
- 首先获取该链表的环开始的节点
- 再定义两个变量来记录返回节点信息,即环开始的节点
- 一个留作备用,另外一个用来比较
- 再定义一个变量来记录环的长度
- 循环是死循环,因为有环链表永远到不了头
- 通过判断现在的节点是否等于环开始节点来跳出循环,并且返回环长度
代码实现:
public static int getCycleLength(Node head) {
// define the variable to record the length
int length = 0;
// judge the list has the loop or not
Node loop = hasLoopReturnNode(head);
// juege the head is null,
if (loop == null)
// true return 0
return length;
// while the head=current the return the length
Node flat = loop;
Node current = loop;
while (current != null) {
current = current.getNext();
length++;
if (current == flat) {
return length;
}
}
return length;
}
测试代码:有环
public class ReverseLinkedListTest {
/**
* @param args
*/
public static void main(String[] args) {
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
node1.setNext(node2);
node2.setNext(node3);
node3.setNext(node4);
node4.setNext(node5);
node5.setNext(node3);
System.out.println(HasLoop.getCycleLength(node1));
}
}
运行结果:
测试代码:无环:
public class ReverseLinkedListTest {
/**
* @param args
*/
public static void main(String[] args) {
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
node1.setNext(node2);
node2.setNext(node3);
node3.setNext(node4);
node4.setNext(node5);
// node5.setNext(node3);
System.out.println(HasLoop.getCycleLength(node1));
}
}
运行结果: