(全)关于链表节点(中间节点及其前驱后驱节点)的双指针查找问题

(全)关于链表节点(中间节点及其前驱后驱节点)的双指针查找问题

LEETCODE很多链表的题目都涉及链表中间节点的查询问题。双指针法是解决这类问题的快速算法。然而由于链表的奇偶数不同,链表为空或者仅仅有一个节点等因素、双指针法很容易出现越界其他特殊情况的细节BUG。在此我针对一些典型节点,整理一些算法。仅供参考。

中间节点及其前驱和后驱节点定义

  • 节点结构体Node
class Node {
	 int val;
	Node *next;
};
  • 中间节点(MidNode)
    奇数链条:对于链表长度为奇数k的链表而言,中间节点为其k/2+1。
    例:1->2->3->4->5 >6->7->8->9->NULL。5为其中间节点。
    偶数链条:对于链表长度为奇数k的链表而言,中间节点为k/2。
    例:1->2->3->4->5 ->6->7->8->NULL。4为其前中间节点。
    当然,存在另一种情况,5也可称之为后中间节点。本文默认为中间节点4
  • 中间结点前驱节点(FRMidNode):为中间节点的前一个节点。
  • 中间节点后驱节点(BEMideNode):为中间节点的后一个节点。

节点查找双指针算法

  • 中间节点查找算法
Node*findMidNode(Node* &head) {
	if (!head || !head->next) return head;
	Node *fast = head, *slow = head;//这里注意,快慢指针是同一点起步。同时如果我们定义偶数链条的后一个节点为中间节点的话,那么此处的*slow = head->next;*fast = head->next;自己可以试一下。
	while (fast->next&&fast->next->next)//这里格外注意:因为fast指针走了两步,所以不是first!=NULL;而是他的第一后继和第二后继!
	{
		fast = fast->next->next;
		slow = slow->next;
	}
	return slow;
  • 中间节点前驱节点查找算法
    这个算法的目的很简单,也很明确。当我们的任务是删除单链表的中间节点时候,我们不得不找到他的前驱节点。这个算法和中间节点查找算法的不同之处。
Node*findRRMidNode(Node* &head) {
	if (!head || !head->next||!head->next->next) return head;//此处要排除两个节点的情况。
	Node *fast = head->next->next, *slow = head;//这里注意一下,因为我们需要寻找中间节点的前驱节点,所以不得不让快指针先走一步。
	while (fast->next&&fast->next->next)//这里格外注意:因为fast指针走了两步,所以不是first!=NULL;而是他的第一后继和第二后继!
	{
		fast = fast->next->next;
		slow = slow->next;
	}
	return slow;
  • 中间节点后驱节点
    这个其实没有必要说的,因为很简答,但是不想改前文内容了,还是说一下吧。直接找到中间节点后,slow指针指向的节点就是了。

案例

【题目描述】给定链表的头结点head,实现删除链表中间节点的函数。
例如:
NULL,不删除任何节点;
1->NULL,不删除任何节点;
1->2->NULL,删除节点1;
1->2->3->NULL,删除节点2;
1->2->3->4->NULL,删除节点2;
1->2->3->4->5->NULL,删除节点3;
[题解]我们需要找到中间节点的前驱节点,然后令他指向中间节点的后驱节点就OK。

Node*delidNode(Node* &head) {
	if (!head || !head->next) return head;
	if (!head->next->next) return head->next;//注意,两个节点的话是无法找到其中间节点的。所以这里特殊处理。

	Node *fast = head->next->next, *slow = head;//这里注意一下,因为我们需要寻找中间节点的前驱节点,所以不得不让快指针先走一步。
	while (fast->next&&fast->next->next)//这里格外注意:因为fast指针走了两步,所以不是first!=NULL;而是他的第一后继和第二后继!
	{
		fast = fast->next->next;
		slow = slow->next;
	}
	slow->next = slow->next->next;
	return head;

**附注:**这里的链表都默认为不带头指针的链表,head为其第一节点。
当循环判断条件为while (fast->next&&fast->next->next),此时快慢指针初始位置和最后循环完毕时,满指针所指示节点关系如下。这里1为链表第一节点。

fast指针初始位置slow指针初始位置最后输出slow指针指向
11前中间节点
22后中间结点
13前中间节点前驱节点
12后中间节点前驱节点
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值