lt.141-环形链表
[案例需求]
[思路分析]
- 环形链表快慢针哈哈, 固定搭配了.
- 同向快慢针一般是fast走两步, slow移动一步, 在探测环时, 由于slow与fast在环内, 随着快指针遍历完一圈后, fast与slow的距离就靠近了一个结点的距离, 经过在圈内多轮的你追我赶, 必将重逢在某一个节点上.
[代码实现]
/**
为什么fast 走两个节点,slow走一个节点,有环的话,一定会在环内相遇呢,而不是永远的错开呢?
首先第一点: fast指针一定先进入环中,如果fast 指针和slow指针相遇的话,一定是在环中相遇,这是毋庸置疑的。
那么来看一下,为什么fast指针和slow指针一定会相遇呢?
这是因为fast是走两步,slow是走一步,其实相对于slow来说,fast是一个节点一个节点的靠近slow的,所以fast一定可以和slow重合。
*/
public class Solution {
public boolean hasCycle(ListNode head) {
//快慢针
if(head == null) return false;
ListNode slow = head.next;
ListNode fast = head.next;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow) return true;
}
return false;
}
}
lt.142-环形链表 II
[案例分析]
[思路分析一, 标记法(会修改链表结点的内容)]
- 把遍历过的结点都通过结点的val打上标记(这个val的值我们设为题目给定范围( node ∈([10的-5次方, 10的5次方])之外;
- 每次遇到的新节点我们先判断是否为标记值, 如果已经是标记值了那就存在环, 如果不是就打上标记, 继续往下遍历, 知道遇到null值或标记值
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head == null || head.next == null)return null;
//标记法
//一次遍历即可
ListNode cur = head;
while(cur != null && cur.val != 2147483647){
cur.val = 2147483647;
cur = cur.next;
}
return cur;
}
}
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head==null)return null;
if(head.val==100001){
return head;
}else{
head.val=100001;
return detectCycle(head.next);
}
}
}
[思路分析二, 哈希表法]
- 遍历链表, 每个遍历后的结点都要加入到List或Map中, 在加入之前我们先进行判断, 如果结合中已经存在这个节点了, 那么肯定存在环, 直接返回这个节点即可
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head == null) return null;
/**
遍历一遍链表, 遍历前添加第一个结点, 每遍历一个结点就把当前节点 temp.next 与 集合中的相比
集合中存在, 则说明有环, 返回当前节点 temp;
由于要求返回的是结点, 所以key为索引, value为ListNode 结点
*/
Map<ListNode, Integer> map = new HashMap<>();
ListNode temp = head;
if(temp.next == temp) return temp;
if(temp.next != null && temp.next != temp) map.put(temp, 0);
int index = 1;
while(true){
if(temp == null) return null;
if(map.containsKey(temp.next)){
return temp.next;
}
map.put(temp, index++);
temp = temp.next;
}
return null;
}
}
[思路分析二, 快慢针法法]
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {// 有环
ListNode index1 = fast;
ListNode index2 = head;
// 两个指针,从头结点和相遇结点,各走一步,直到相遇,相遇点即为环入口
while (index1 != index2) {
index1 = index1.next;
index2 = index2.next;
}
return index1;
}
}
return null;
}
}