快慢指針:快慢指針是解決數組和鏈表問題的常用方法,該方法也被稱爲“龜兔算法”。從名稱就可以看出氣基本思想是使用兩個指針以不同的速度在數組或鏈表中移動。在處理循環鏈表或數組時,此方法非常有用。
快慢指針的應用:
(1)判斷單鏈表是否存在環
如果鏈表存在環,就好像操場的跑道是一個環形一樣,此時讓快慢指針都從鏈表頭開始遍歷,快指針每次向前移動兩個位置,慢指針每次向前移動一個位置;如果快指針到達NULL,說明鏈表以NULL爲結尾,沒有環。如果快指針追上慢指針,則表示有環。代碼如下:
bool HasCircle(Node *head)
{
if(head == 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;
}
(2)在有序鏈表中尋找中位數
快指針的移動速度是慢指針移動速度的2倍,因爲當快指針到達鏈表尾時,慢指針到達中點。
程序還要考慮鏈表結點個數的奇偶數因素,當快指針移動x次後到達表尾(1+2x),說明鏈表有奇數個結點,直接返回慢指針指向的數據即可。
如果快指針是倒數第二個結點,說明鏈表結點個數是偶數,這時可以根據”規則“返回上中位數或下中位數或(上中位數+下中位數)的一半。
while (fast && slow)
{
if(fast->next == NULL)
return slow->data;
else if (fast->next != NULL && fast->next->next == NULL)
return (slow->data + slow->next->data)/2;
else
{
fast = fast->next;
fast = fast->next;
slow = slow->next;
}
}
(3)輸出鏈表中的倒數第K個結點(即正數第k-1個節點)
可以定義兩個指針,第一個指針從鏈表的頭指針開始遍歷向前走K-1步,第二個指針保持不動;從第K步開始,第二個指針也開始從鏈表的頭指針開始遍歷。由於兩個指針的距離保持在K-1,當第一個指針到達鏈表的尾節點時候,第二個指針正好是倒數第K個節點,代碼如下:
//查找單鏈表中倒數第K個結點
ListNode * RGetKthNode(ListNode * pHead, unsingnes int k)//函數前面的R代表反向
{
if(k == 0 || pHead == NULL)//這裏k的計數是從1開始的,若k爲0或鏈表爲空返回NULL
return NULL;
ListNode * pAhead = pHead;
ListNode * pBehind = pHead;
for(int i=0; i<k-1;i++)
{
pAhead=pAhead->next;
if(pAhead==NULL)
return NULL;//當鏈表長度小於k時候,返回NULL
}
while(pAhead->next !=NULL )//前後兩個指針一起向前走,知道前面的指針指向最後一個結點
{
PBehind = pBehind->next;
pAhead = pAhead->next;
}
return pBehind;//後面的指針所指結點就是倒數第K個結點
參考鏈接:
https://blog.csdn.net/qq_21815981/article/details/79833976