最好的,不一定是最合适的;最合适的,才是真正最好的。💓💓💓
目录
说在前面
题目一:分割链表
题目二:环形链表的约瑟夫问题
SUMUP结尾
说在前面
dear朋友们大家好!💖💖💖数据结构的学习离不开刷题,继上次算法OJ练习1,我们继续进行链表经典算法的练习。当然除了了LeetCode,有些题也会在NowCoder上,大家可以在这两个网站上进行练习。
👇👇👇
友友们!🎉🎉🎉点击这里进入力扣leetcode学习🎉🎉🎉
以下是leetcode题库界面:
👇👇👇
🎉🎉🎉点击这里进入牛客网NowCoder刷题学习🎉🎉🎉
以下是NowCoder题库界面:
题目一:分割链表
题目链接:面试题 02.04. 分割链表 - 力扣(LeetCode)
题目描述:
题目分析:
思路:创建大小链表,若pcur节点的值小于x则插入小链表,若pcur节点的值大于x则插入大链表,再将大小链表连接。
注意,实际上小链表的lesstail指向了原链表中数据为5的节点,而大链表的greatertail指向了原链表中数据为2的节点。所以在连接大小链表时,除了将小链表中的lesstail的next指针指向大链表中的第一个有效节点(而非头节点)greaterhead->next,还需要将大链表中的greatertail的next指针置空,否则将形成循环链表。
代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* partition(struct ListNode* head, int x) {
//单独讨论空链表的情况
if(head==NULL)
return NULL;
//创建大小指针
ListNode* lesshead=(ListNode*)malloc(sizeof(ListNode));
ListNode* lesstail=lesshead;
ListNode* greaterhead=(ListNode*)malloc(sizeof(ListNode));
ListNode* greatertail=greaterhead;
ListNode* pcur=head;
//遍历数组
while(pcur)
{
if(pcur->val<x)//放入小链表
{
lesstail->next=pcur;
lesstail=pcur;
}
else//放入大链表
{
greatertail->next=pcur;
greatertail=pcur;
}
pcur=pcur->next;
}
greatertail->next=NULL;//结尾置NULL
lesstail->next=greaterhead->next;连接大小链表
ListNode* ret=lesshead->next;//保存第一个有效节点
//释放动态申请的空间
free(lesshead);
free(greaterhead);
return ret;
}
题目二:环形链表的约瑟夫问题
题目链接:环形链表的约瑟夫问题_牛客题霸_牛客网 (nowcoder.com)
背景:著名的约瑟夫问题
据说犹太著名历史学家 Josephus 有过一下的故事:在罗马人占领乔塔帕特后,39个犹太人与Joesphus 及他的朋友躲到一个洞中,39个犹太人决定宁死也不要被人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,知道所有人都自杀身亡为止。
然而 Josephus 和他的朋友并不想遵从,Josephus 要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
题目描述:
题目分析:
思路:利用count计数,count为m时删除所对应的节点,直到剩下一个节点。
我们以约瑟夫事件原型为例,此时n=5,m=3,我们需要先创建这样一个带环链表,将它封装为函数circle,而创建链表就需要申请节点,将其封装为函数ListBuyNode,同时需要在带环链表中把每个节点的数据设置好,这个行为我们可以用for循环完成。
创建好链表后,我们需要创建两个指针:pcur用来遍历链表,每每遍历到下一个节点count++,如果遍历的过程中count达到m,就删除这个节点,此时需要将pcur的前一个指针指向pcur的后一个指针,所以我们还需要指针prev来记录pcur的前一个指针,以此往复,直到只剩下一个节点,此时pcur->next指向pcur它自己,所以循环条件就是pcur->next!=pcur。
代码如下:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param n int整型
* @param m int整型
* @return int整型
*/
typedef struct ListNode ListNode;
//创建节点
ListNode* ListBuyNode(int x)
{
ListNode* node=(ListNode*)malloc(sizeof(ListNode));
if(node==NULL)
{
perror("malloc");
exit(1);
}
node->val=x;
node->next=NULL;
return node;
}
//创建带环链表
ListNode* circle(int n)
{
ListNode* phead=ListBuyNode(1);
ListNode* ptail=phead;
for(int i=2;i<=n;i++)
{
ptail->next=ListBuyNode(i);
ptail=ptail->next;
}
ptail->next=phead;
return ptail;
}
int ysf(int n, int m)
{
//创建关于n的带环链表
ListNode* prev=circle(n);
ListNode* pcur=prev->next;
int count=1;
while(pcur!=pcur->next)
{
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;
}
约瑟夫问题是循环链表的经典应用,大家重视起来,务必熟练掌握。
SUMUP结尾
数据结构就像数学题,需要刷题才能对它有感觉。之后还会更新数据结构相关的练习题、面试题,希望大家一起学习,共同进步~
如果大家觉得有帮助,麻烦大家点点赞,如果有错误的地方也欢迎大家指出~