4.链表的中间节点
单链表相关经典算法OJ题4:
链表的中间结点
. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/middle-of-the-linked-list/
思路:
问题的关键也在于我们无法直接得到单链表的长度 n,常规方法也是先遍历链表计算 n,再遍历一次得到第 n / 2 个节点,也就是中间节点。
如果想一次遍历就得到中间节点,也需要耍点小聪明,使用「快慢指针」的技巧:
我们让两个指针 slow 和 fast 分别指向链表头结点 head。
每当慢指针 slow 前进一步,快指针 fast 就前进两步,这样,当 fast 走到链表末尾时,slow 就指向了链表中点。
实现代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* middleNode(struct ListNode* head)
{
struct ListNode*fast=head,*slow=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
}
return slow;
}
5.环形链表的约瑟夫问题
循环链表经典应⽤-环形链表的约瑟夫问题环形链表的约瑟夫问题_牛客题霸_牛客网编号为 1 到 n 的 n 个人围成一圈。从编号为 1 的人开始报数,报到 m 的人离开。。题目来自【牛客题霸】https://www.nowcoder.com/practice/41c399fdb6004b31a6cbb047c641ed8a
思路:
- 成环, 返还tail结点
- 初始化前哨指针,和当前指针
- 遍历计数,当技术等于m了,则摘掉当前结点,从下个结点开始
- 返回最一个指针,即当前指针的val
代码实现:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param n int整型
* @param m int整型
* @return int整型
*/
typedef struct ListNode ListNode;
//创建节点
ListNode* buyNode(int x)
{
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
if (node == NULL)
{
exit(1);
}
node->val = x;
node->next = NULL;
return node;
}
//创建带环链表
ListNode*createCircle(int n)
{
//先创建第一个节点
ListNode* phead = buyNode(1);
ListNode* ptail = phead;
for (int i = 2; i <= n; i++)
{
ptail->next = buyNode(i);
ptail = ptail->next;
}
//首尾相连,链表成环
ptail->next = phead;
return ptail;
}
int ysf(int n, int m)
{
//1.根据n创建带环链表
ListNode* prev = createCircle(n);
ListNode* pcur = prev->next;
int count = 1;
//当链表中只有一个节点的情况
while (pcur->next!=pcur)
{
if (count == m)
{
//销毁pcur节点
prev->next = pcur->next;
free(pcur);
pcur = prev->next;
count = 1;
}
else
{
//此时不需要销毁节点
prev = pcur;
pcur = pcur->next;
count++;
}
}
//此时剩下的一个节点就是要返回的节点里的值
return pcur->val;
}
6.合并两个有序链表
单链表相关经典算法OJ题6:
分割链表
. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/partition-list-lcci/
思路:
创建大小链表,比x大的插入大链表,比x小的插入小链表。
代码实现:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode ListNode;
struct ListNode* partition(struct ListNode* head, int x)
{
//创建两个带头链表
ListNode* lessHead, * lessTail;
ListNode* greaterHead, * greaterTail;
lessHead = lessTail = (ListNode*)malloc(sizeof(ListNode));
greaterHead = greaterTail = (ListNode*)malloc(sizeof(ListNode));
//遍历原链表,将原链表的节点尾插到大小链表中
ListNode* pcur = head;
while(pcur)
{
if (pcur->val < x)
{
//尾插到小链表中
lessTail->next = pcur;
lessTail = lessTail->next;
}
else
{
//尾插到大链表中
greaterTail->next = pcur;
greaterTail = greaterTail->next;
}
pcur = pcur->next;
}
//修改大链表的尾节点的next指针指向
greaterTail->next = NULL;//若不加这一行,代码会出现死循环
//小链表的尾节点和大链表的第一个有效节点首尾相接
lessTail->next = greaterHead->next;
ListNode* ret = lessHead->next;
free(lessHead);
free(greaterHead);
lessHead = greaterHead = NULL;
return ret;
}
本篇文章介绍了题目的部分解法。如果本篇有补充的地方,欢迎私信我或在评论区指出,期待与你们共同进步。