链表拆分与快慢指针相关算法题
一拆分为二
设
C
=
a
1
,
b
1
,
a
2
,
b
2
,
…
,
a
m
,
b
m
C={a_{1},b_{1},a_{2},b_{2},\dots,a_{m},b_{m}}
C=a1,b1,a2,b2,…,am,bm,为线性表,采用带头节点的单链表存放,将其拆分为两个线性表
使得
A
=
a
1
,
a
2
,
…
,
a
n
A=a_{1},a_{2},\dots,a_{n}
A=a1,a2,…,an,
B
=
b
n
,
…
,
b
2
,
b
1
B=b_{n},\dots,b_{2},b_{1}
B=bn,…,b2,b1
算法思想
循环遍历链表C,
采用尾插法将一个节点插入表A,这个节点为奇数号节点,这样建立的表A与原来的节点顺序相同;
采用头插法将下一节点插入表B,这个节点为偶数号节点,这样建立的表B与原来的节点顺序正好相反
malloc一个B头节点,将B的next指向NULL
用一个工作指针cur来指向A表的第一个节点,准备遍历A表
用一个tail指针指向A头节点,用来尾插找尾
cur往后遍历A表,直到cur指向空时结束
将tail的next也就是A的next指向cur,这里不动
tail指针后移,指向A表的最后一个节点
cur指向cur的next,后移一位
这时候cur走向偶数位置,判断cur是否指向空
用next保存cur的下一个节点
cur的next指向B的next,将cur头插到B表
B的next指向cur
cur指向next
再进行A表的尾插
再进行B表的头插
将tail的next指向NULL
LinkList DisCreat(LinkList &A)
{
LinkList B = (LinkList)malloc(sizeof(LNode)); //创建B表表头
B->next = NULL; //B表初始化
LNode* cur = A->next, *next; //cur为工作指针
LNode* tail = A; //tail始终指向A的尾节点
while (cur)
{
tail->next = cur; //将*cur链到A的表尾
tail = cur;
cur = cur->next;
if (cur)
{
next = cur->next; //头插后,*cur将断链,用next记忆*cur的后继
cur->next = B->next; //将*cur插入到B表的前端
B->next = cur;
cur = next;
}
}
tail->next = NULL; //A尾节点的next指向NULL
return B;
}
判断链表是否带环
单链表有环,是指单链表的最后一个节点的指针指向了链表中的某个节点,判断单链表是否存在环
算法思想
设置快慢指针分别为fast和slow最初都指向链表头head
slow每次走一步,fast每次走两步
fast走得比slow快,若有环,则fast一定先进入环
两个指针进入环后,一定会在环上相遇
链表分割|链表的回文结构|相交链表|环形链表|随机链表的复制©-CSDN博客
这里有详细说明过程,环形链表1和2
LNode* FindLoopStart(LNode* head)
{
LNode* fast = head, *slow = head; //设置两个快慢指针
while (fast && fast->next)
{
slow = slow->next; //每次走一步
fast = fast->next->next; //每次走两步
if (slow == fast) //相遇
break;
}
if (fast == NULL || fast->next == NULL)
return NULL; //没有环,返回空
LNode* p1 = head, *p2 = slow; //分别指向开始点,相遇点
while (p1 != p2)
{
p1 = p1->next;
p2 = p2->next;
}
return p1; //返回入口点
}
一个指针从头节点开始走,一个节点从相遇点开始走,当两个指针相遇的时候,就是入口点
返回倒数第k个节点
输入一个链表,输出该链表的倒数第k个节点
算法思想
快慢指针思想
将fast指针指向链表的第k+1个节点,slow指向链表的第一个节点,此时fast和slow之间刚好相差k个节点,两个指针同步向后走,当fast走到链表的尾部空节点时,slow指针正好指向链表的倒数第k个节点
fast先走k步,之后同步走
直到fast指向空
LNode* getKthFromEnd(LinkList &head, int k)
{
if (head == NULL)
return NULL;
LNode* fast = head, *slow = head;
int i = 0;
while (fast)
{
if (i >= k)
{
slow = slow->next;
}
fast = fast->next;
i++;
}
return slow;
}