1 单向链表反转
2 快慢指针
快慢指针指的就是定义两个指针,这两个指针的移动速度一块一慢,快慢指针之间的差值可以让我们找到链表中的相应节点。一般情况下,快指针的移动步长为慢指针的两倍。
2.1 中间值问题
利用快慢指针查找链表中间节点。
原理:快慢指针初始位置为链表头,快指针移动步长2倍于慢指针,当快指针移动到链表末尾的时候,慢指针刚好移动到链表中间位置。
链表有7个节点,分别存储字符串aa,bb,cc,dd,ee,ff,gg,蓝色表示慢指针,每次移动一个节点位置;绿色表示快指针,每次移动2个节点位置,当绿色指针移动到链表结尾时,蓝色节点刚好移动到中间节点位置dd处。如图2.1-1所有:
用代码模拟实现,代码2.1-1如下:
public class FastSlowPointerTest {
public static void main(String[] args) {
Node<String> seven = new Node<>("gg", null);
Node<String> six = new Node<>("ff", seven);
Node<String> five = new Node<>("ee", six);
Node<String> four = new Node<>("dd", five);
Node<String> three = new Node<>("cc", four);
Node<String> two = new Node<>("bb", three);
Node<String> one = new Node<>("aa", two);
System.out.println(getMid(one));
}
public static String getMid(Node<String> first) {
Node<String> fast = first;
Node<String> slow = first;
while (fast != null && fast.next != null) {
fast = fast.next.next;
if (fast == null) {
break;
}
slow = slow.next;
}
return slow.item;
}
private static class Node<E> {
E item;
Node<E> next;
public Node(E item, Node<E> next) {
this.item = item;
this.next = next;
}
}
}
2.2 单向链表是否有环
无环链表,前一节点指向后一节点,而后面节点不指向前面节点,如图2.2-1所示:
有环链表,前一节点指向后一节点,且后面节点指向前面节点,如图2.2-2所示:
快慢指针查找是否有环原理:快指针移动快,如有环路,当慢指针进入环路时,快指针已经在环路中,且快指针移动快,一直移动直至快慢指针相遇;如果没有环路,则快指针和慢指针不会相遇。
快慢指针查找环路图示2.2-3:
用代码模拟实现,代码2.2-1如下:
public class LinkListCircuitTest {
public static void main(String[] args) {
Node<String> seven = new Node<>("gg", null);
Node<String> six = new Node<>("ff", seven);
Node<String> five = new Node<>("ee", six);
Node<String> four = new Node<>("dd", five);
Node<String> three = new Node<>("cc", four);
Node<String> two = new Node<>("bb", three);
Node<String> one = new Node<>("aa", two);
seven.next = three;
System.out.println(isCircuit(one));
}
public static boolean isCircuit(Node<String> first) {
Node<String> fast = first;
Node<String> slow = first;
while (fast != null && fast.next != null) {
fast = fast.next.next;
if (fast == null) {
break;
}
slow = slow.next;
if (fast == slow) {
return true;
}
}
return false;
}
private static class Node<E> {
E item;
Node<E> next;
public Node(E item, Node<E> next) {
this.item = item;
this.next = next;
}
}
}
2.3 有环链表入口
当检测的链表有环后,怎么找到入口呢?当快慢指针相遇时,这是重新设定一个新的指针指向链表的启点,且步长与慢指针一样为1,则慢指针与“新”指针相遇的地方就是环的入口。证明涉及数论的知识,本人还没有学,略过。
代码实现如下:
public static Node<String> getEntrance(Node<String> first) {
Node<String> fast = first;
Node<String> slow = first;
Node<String> temp = null;
while (fast != null && fast.next != null) {
fast = fast.next.next;
if (fast == null) {
break;
}
slow = slow.next;
if (fast == slow) {
temp = first;
continue;
}
if (temp != null) {
temp = temp.next;
if (temp == slow) {
return slow;
}
}
}
return null;
}
测试代码同2.2一致
3 后记
? 如果小伙伴什么问题或者指教,欢迎交流。
?QQ:806797785
??源代码仓库地址:https://gitee.com/gaogzhen/algorithm
参考:
[1]黑马程序员.黑马程序员Java数据结构与java算法全套教程,数据结构+算法教程全资料发布,包含154张java数据结构图[CP/OL].p56~p60.
|