1、链表环
1.1 判断单链表是否存在环
设置两个节点:slow、fast,若存在环,分别从链表的头节点出发,一个每次向后移动一步,另一个移动两步,两个指针移动速度不一样,如果存在环,那么两个指针一定会在环里相遇。
public boolean hasCircle(Node head) {
if (head == null || head.next == null) {
return false;
}
Node slow = head;
Node fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
return true;
}
}
return false;
}
1.2 带环单链表的入口节点
头结点和相遇结点时,将slow指向root,同步前进,则最后一定相遇在环入口结点。
/**
* 返回循环的入口节点:
* <p>
* slow: a + b = n
* fast: a + b + kL = 2n
* <p>
* 相遇时:n = kL = a+b
* <p>
* slow 再走 n 步的话,还可以再回到相遇点,
* fast 从头开始走的话,经过n步,也会达到相遇点M
*
* @return
*/
public Node findLoopEnter(Node head) {
if (head == null || head.next == null) {
return null;
}
Node slow = head;
Node fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
break;
}
}
if (slow != fast) {
return null;
}
fast = head;
while (fast != slow) {
fast = fast.next;
slow = slow.next;
}
return fast;
}
1.3 单链表环的长度
// 获取环的入口地址、循环一圈、每次加1
public int circleLength(Node root){
Node node=searchEntranceNode(root);
if(node==null){
return 0;
}
Node n=node.next;
int length=1;
while(n!=node){
length++;
n=n.next;
}
return length;
}
1.4 两个无环链表交点
两个无环单链表是否相交,给出相交的第一个结点
- 方法1
将其中一个链表首尾相连,检测另外一个链表是否存在环;如果存在,则两个链表相交,而检测出来的环入口即为相交的第一个结点
。 - 方法2
如果两个链表相交,那个两个链表从相交点到链表结束都是相同的节点。我们可以先遍历一个链表,直到尾部,再遍历另外一个链表,如果也可以走到同样的结尾点,则两个链表相交。这时我们记下两个链表的长度,再遍历一次。长链表节点先出发前进(长链表长度-短链表长度)步,之后两个链表同时前进,每次一步,相遇的第一点即为两个链表相交的第一个点
。
/**
* 无环链表相交的节点:
* 方法1、先计算长度,在同步走比较
* <p>
* 方法2、递归或栈逆向对比
*
* @return
*/
public Node findIntersectNode(Node head1, Node head2) {
if (head1 == null || head2 == null){
return null;
}
Stack<Node> stack1 = new Stack<>();
Stack<Node> stack2 = new Stack<>();
while (head1 != null){
stack1.push(head1);
head1 = head1.next;
}
while (head2 != null){
stack2.push(head2);
head2 = head2.next;
}
Node point = null;
while (!stack1.isEmpty() && !stack2.isEmpty()){
Node node1 = stack1.pop();
Node node2 = stack2.pop();
if (node1 == node2){
point = node1;
}else {
break;
}
}
return point;
}
两个有环链表是否相交
找到第一个链表的环点,然后将环断开(当然不要忘记了保存它的下一个节点),然后再来遍历第二个链表 ,如果发现 第二个链表从有环变成了无环,那么他们就是相交的嘛,否则就是不相交的了.
两个环相交必定存在公共的循环链部分,断开一个环另一个必定断开
注: 当一个链表中有环,一个链表中没有环时,两个链表必不相交