快慢指针的常见应用

快慢指针:快慢指针是解决数组和链表问题的常用方法,该方法也被称为“龟兔算法”。从名称就可以看出气基本思想是使用两个指针以不同的速度在数组或链表中移动。在处理循环链表或数组时,此方法非常有用。

快慢指针的应用

(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.youkuaiyun.com/qq_21815981/article/details/79833976

### 快慢指针算法概述 快慢指针是一种常见的双指针技术,通过设置两个不同速度的指针在一维数据结构(如数组或链表)上移动来解决问题。通常情况下,快指针每次向前移动两步或多步,而慢指针每次只前进一步[^2]。 #### 快慢指针的核心思想 核心在于利用两者之间的相对速度差异,从而达到特定的目标位置或者检测某些特性。例如,在处理单向链表时,可以通过这种方式轻松定位到中间节点、判断是否存在以及查找的入口等[^3]。 --- ### 快慢指针应用场景及其实现 #### 应用场景 1:寻找链表的中间节点 为了找到链表的中间节点,可以让快指针一次前进两步,慢指针一次前进一步。当快指针到达链表末端时,慢指针正好位于链表的中间位置。 ```python def find_middle_node(head): slow, fast = head, head while fast and fast.next: slow = slow.next # 慢指针走一步 fast = fast.next.next # 快指针走两步 return slow # 返回中间节点 ``` --- #### 应用场景 2:判断链表是否 如果链表存在,则快指针最终会追上慢指针;反之则不存在。此逻辑基于快慢指针的速度差使得它们能够在有限时间内相遇[^4]。 ```python def has_cycle(head): slow, fast = head, head while fast and fast.next: slow = slow.next # 慢指针走一步 fast = fast.next.next # 快指针走两步 if slow == fast: # 如果相遇说明有 return True return False # 否则无 ``` --- #### 应用场景 3:找出的入口节点 假设链表中有,那么可以先让快慢指针分别从头结点出发直到第一次相遇。接着重置其中一个指针回到头部,并使二者均以相同速率逐步前行直至再度交汇处即为起点。 ```python def detect_cycle_entry(head): slow, fast = head, head # 判断是否存在 while fast and fast.next: slow = slow.next fast = fast.next.next if slow == fast: break # 首次相遇 if not (fast and fast.next): # 若未形成闭返回None return None # 找到入口 slow = head # 将慢指针移回起始位置 while slow != fast: # 当二者的距离等于0时表示找到了入点 slow = slow.next fast = fast.next return slow # 返回入口节点 ``` --- ### 总结 快慢指针作为一种高效且简洁的技术手段广泛应用于各种复杂度较高的问题之中,诸如上述提到过的获取列表中心项、检验循状况乃至确定具体进入路径等方面都发挥着不可替代的重要作用[^1]. ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值