最近在刷leetcode oj,在做题过程中发现有很多题目的解法里都用到了快慢指针,之前对这个概念接触很少,所以做以下总结:
首先考虑一个简单的问题,寻找链表的中间节点,这个问题是快慢指针应用的典型问题,java代码段如下:
public ListNode getMid(ListNode head){
ListNode slow = head;
ListNode fast = head;
while(fast!= null && fast.next != null && fast.next.next !=null ){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
该方法一开始将快慢指针都指向头节点,然后慢指针每次移动一步,快指针一次移动两步,直到快指针到达末尾慢指针的位置就是链表的中间节点位置。
快慢指针还有其它方面的应用,判断链表是否存在环和找出环开始的位置也是快慢指针大显身手的地方,先看判断链表是否存在环的问题,java代码如下:
public boolean hasCycle(ListNode head) {
if(head == null || head.next == null)
return false;
ListNode slow = head;
ListNode fast = head;
while(fast != null && fast.next != null && fast.next.next != null){
slow = slow.next;
fast = fast.next.next;
if(slow == fast)
return true;
}
return false;
}
利用快慢指针,如果链表有环的话,快指针和慢指针肯定会相遇,这跟环型跑道赛跑是一个道理。
在这基础上扩展不难提出这样的问题,如果链表存在环,那么如何找到环的起点,先上java代码:
public ListNode detectCycle(ListNode head) {
if(head == null || head.next == null)
return null;
ListNode slow = head;
ListNode fast = head;
ListNode begin = null;
while(fast != null && fast.next != null && fast.next.next != null){
slow = slow.next;
fast = fast.next.next;
if(slow == fast){
slow = head;
while(slow != fast){
slow = slow.next;
fast = fast.next;
}
begin = slow;
break;
}
}
return begin;
}
思路就是当快慢指针相遇的时候让慢指针指向头节点,快指针变成每次移动一步,当两个指针相遇的时候,那个节点就是环的起点。
具体可以参考以下链接:http://umairsaeed.com/2011/06/23/finding-the-start-of-a-loop-in-a-circular-linked-list/