目录
1、环形链表 |
题目描述:
思路:要我们判断链表中是否有环,如果有环就意味着链表没有中止点,会进入循环;
所以我们只需要引入一个快慢指针,快指针fast每次移动两个节点,慢指针slow每次移动一个节点
所以只要链表有环,快慢指针必定有相交的一刻,相交后就返回true;
如果无环,那我只要当fast ==null || fast.next == null时,退出循环即可,返回false;
看看代码:
public boolean hasCycle(ListNode head) {
if(head == null) return false;
ListNode fast = head,slow = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow) return true;
}
return false;
}
2、环形指针 ||
题目描述:
思路: 首先我们依旧采用第一题的快慢指针的思路,fast指针一次走两步,slow指针一次走一步
设从head到环开始的距离为a,环的长度为b,fast指针走过的距离f,慢指针走过的距离s
首先我们能确定的是,当快慢指针第一次相遇时:
由于快指针一次走两步,慢指针一次一步,所以f = 2s
快指针与慢指针相遇,就要比满指针多走n个环的距离,f = s + nb;
我们可以得到f = 2nb,s = nb;
我们慢指针s第一次相遇走了nb,又可知如果慢指针想走到环开始的位置要走a + nb
所以我们只需要让慢指针再走a步,就可以到达指定位置;
所以我们再次设置双指针,设置另一个指针在head位置,当这个指针再与慢指针slow,相遇时,正好又走了a步,此时到达指定位置;
代码如下:
public ListNode detectCycle(ListNode head) {
ListNode fast = head,slow = head;
while(true){
if(fast == null || fast.next == null) return null;
fast = fast.next.next;
slow = slow.next;
if(fast==slow) break;
}
fast = head;
while(fast != slow){
fast = fast.next;
slow = slow.next;
}
return fast;
}