一、概念
快慢指针主要应用于查找链表或迭代函数中是否存在循环。
定义两个相同数据结构的指针,区别在于慢指针和快指针的移动步长step可以不同。在每次迭代循环中,快指针与慢指针之间的距离可以拉开或不同,来完成我们想要的目的。
根据step设定的不同,可以区分几种情况:
(1) 快慢指针的移动距离可以相差倍数 【例1】【例2】【例3】
(2) 快慢指针的移动距离可以相差固定值 【例4】
二、应用
例1. 【leet_876】Middle of the Linked List
使用快慢指针的典型案例,slow_step=1, fast_step=2,就可以保证当fast_step到最后节点时,slow_step到达中间节点。
fast_point=1+2t 到达最后节点,则表示链表数量为奇数,则slow_point=1+t 是中间节点。
fast_point=1+2t+1=2(1+t) 到达最后节点,表示链表数量为偶数,则slow_point=1+t 为中间节点的第一个。
class Solution {
public:
ListNode* middleNode(ListNode* head)
{
ListNode* slow_point = head;
ListNode* fast_point = head;
while( fast_point->next && fast_point->next->next )
{
slow_point=slow_point->next;
fast_point=fast_point->next->next;
}
// 若数量为偶数,直接输出第一个中间节点,则如下:
// return slow_point;
// 若数量为偶数,直接输出第二个中间节点,则如下:
if(!fast_point->next)
return slow_point;
else
return slow_point->next;
}
};
例2. 【leet_141】判断单链表中是否存在循环
代码:
class Solution {
public:
bool hasCycle(ListNode *head)
{
if(!head || !head->next || !head->next->next)
return false;
ListNode *fast_point = head;
ListNode *slow_point = head;
while(fast_point && fast_point->next)
{
slow_point = slow_point->next;
fast_point = fast_point->next->next;
if(fast_point == slow_point)
return true;
}
return false;
}
};
例3. 【leet_202】判断Happy Number
Happy Number指的是任意数字经过多次迭代后,能够为1,迭代方式如下:
是Happy Number:
非Happy Number:
代码:
class Solution {
public:
int digitSquareSum(int n) {
int temp = n;
int new_number=0;
while(temp){
new_number += pow(temp-(temp/10)*10,2);
temp = temp/10;
}
return new_number;
}
bool isHappy(int n) {
if(n==1)
return true;
int slow_number = n;
int fast_number = n;
slow_number = digitSquareSum(slow_number);
fast_number = digitSquareSum(fast_number);
fast_number = digitSquareSum(fast_number);
while(fast_number!=1){
slow_number = digitSquareSum(slow_number);
fast_number = digitSquareSum(fast_number);
fast_number = digitSquareSum(fast_number);
if(slow_number == fast_number)
return false;
}
return true;
}
};
例4. 【leet_019】去除链表倒数第N个结点
fast_point=t+N 到达最后节点时,slow_point=t 正好是倒数第N个结点。
边界条件: N为链表结点数量时,去除的是头节点。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n)
{
ListNode* slow_list = head;
ListNode* fast_list = head;
while(fast_list)
{
fast_list = fast_list->next;
n--;
if(n<-1)
{
slow_list = slow_list->next;
}
}
if(n==0)
head= head->next;
else
slow_list->next = slow_list->next->next;
return head;
}
};
其他快慢指针文献: