快慢指標即使用一快一慢兩個指標,對連結串列進行遍歷。利用兩個指標的速度差,如2倍速-用於求中間指標或迴圈連結串列;恆定n個差值,用於尋找倒數第n個指標。
1. 環形連結串列
如果快指標到達NULL,說明連結串列以NULL結尾,不存在環。如果快指標追上慢指標,則表示有環。
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) {
return false;
}
ListNode slow = head;
ListNode fast = head.next;
while (slow != fast) {
if (fast == null || fast.next == null) {
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
}
2. 找中間值
我們把一個連結串列看成一個跑道,假設a的速度是b的兩倍,那麼當a跑完全程後,b剛好跑一半,以此來達到找到中間節點的目的。
publicListNode endOfFirstHalf(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
3. 刪除倒數第N個節點
快指標先走n步,慢指標開始和快指標同步移動到next,當快指標到達連結串列尾部時,慢指標剛好移動到倒數第n-1個節點。
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode fast = head;
ListNode slow = head;
//慢指標比快指標慢N步,那麼快指標指向末尾的null時,慢指標剛好指向要刪除結點的前驅結點
while (fast.next != null) {
fast = fast.next;
if (n == 0) {
slow = slow.next;
} else {
n--;
}
}
if (n != 0) { //沒追上,說明刪除的是頭指標
return head.next;
} else {
slow.next = slow.next.next;
}
return head;
}
總結
快慢指標在連結串列類的迭代中,時間複雜度是O(n)的量級,是一種能有效控制時間複雜的演算法。