「题解」环形链表的约瑟夫问题
最佳答案 问答题库728位专家为你答疑解惑
文章目录
- 🍉题目
- 🍉解析
- 🍌创建环形链表
- 🍌释放指定节点
- 🍌其他思路
- 🍉写在最后
🍉题目
🍉解析
题目的意思就是从环形链表的第一个节点开始数,数到第 m 的时候释放对应的节点,然后从下个节点又从1开始数,然后继续释放节点。所以我们要做的就是通过循环不断删除指定位置的节点。比如有5个节点,在删除第二个节点之前,得先让第一个节点的 next 指向第三个。
不过题目现在还没有链表,我们得先来创建一个。
(下面这个图演示有五个节点,m = 2的情况,绿色箭头表示删除某些节点之后剩余节点 next 指针的指向)
🍌创建环形链表
环形链表和单链表的区别在于,环形它最后一个节点的 next 指向的是第一个节点而非NULL,
既然首尾节点有这种联系,那一开始就得建立这两个指针phead
和ptail
,等下创建链表的时候ptail
就在循环中不断往后走,当它走到最后一个节点时,就让该节点的next指向第一个节点。
既然要产生节点,那么先来写个创建节点的函数(前面的文章有讲),代码如下:
ListNode* BuyListNode(int i) {ListNode* node = (ListNode*)malloc(sizeof(ListNode));node->val = i;node->next = NULL;return node;
}
接下来要创建链表,这个也不难:
ListNode* CreatListNode(int n) {ListNode* phead = BuyListNode(1);ListNode* ptail = phead;for (int i = 2;i <= n ; i++) { //注意循环从 i == 2开始ListNode* node = BuyListNode(i);ptail->next = node;ptail = ptail->next; }ptail->next = phead;return ptail;
}
注意:
①题目有说节点个数可以为1,检查下节点数为1有没有问题,此时首尾节点是同一个,而且不会进入循环,没问题。
②这里返回的是ptail,因为返回它的话我们很容易就能找到phead,而如果返回phead,那要找ptail的话还要遍历链表。
🍌释放指定节点
因为涉及到多次释放节点,不难想到应该要用while循环,那循环终止条件是啥呢?暂时看不出来,先把循环里面的东西写一下再说。
如上图,调用创建链表函数后,我们用prev
接收返回的节点地址(其实就是尾节点),然后定义一个phead
(prev->next)作为头指针,再来一个计数器,只要计数器的值为m,就先让prev
保存phead
的下一个节点,然后删除phead
所指节点,然后让phead
走向下一节点;若 count 不为m,则让phead
和prev
都前进一步。下面再画个图方便你理解这个过程。
再来说下循环结束条件,按照我刚才上面画的图,按那个走势走下去,最后只剩下节点3,此时phead
和phead的next
重合了,就可以出循环了,然后返回节点的值。
所以代码如下:
int ysf(int n, int m ) {ListNode* prev = CreatListNode(n);ListNode* phead = prev->next;int count = 1; while (phead->next != phead) {if(count == m) {prev->next = phead->next;free(phead);phead = prev->next;count = 1; //注意count一定要置为1!} else {prev = phead;phead = phead->next;count++;}}return phead->val;
}
整道题的代码如下:
typedef struct ListNode ListNode;ListNode* BuyListNode(int i) {ListNode* node = (ListNode*)malloc(sizeof(ListNode));node->val = i;node->next = NULL;return node;
}ListNode* CreatListNode(int n) {ListNode* phead = BuyListNode(1);ListNode* ptail = phead;for (int i = 2;i <= n ; i++) {ListNode* node = BuyListNode(i);ptail->next = node;ptail = ptail->next; }ptail->next = phead;return ptail;
}int ysf(int n, int m ) {ListNode* prev = CreatListNode(n);ListNode* phead = prev->next;int count = 1;while (phead->next != phead) {if(count == m) {prev->next = phead->next;free(phead);phead = prev->next;count = 1;} else {prev = phead;phead = phead->next;count++;}}return phead->val;
}
🍌其他思路
在上面演示的例子中,你也可以定义phead
和pcur
,其中pcur
指向第二个节点,不过此时count的初始值要置为2。
🍉写在最后
如果你觉得本文写得还不错的话,那就点个小小的赞和关注喔,你们的支持是我更新的不懈动力!
99%的人还看了
相似问题
- 〖大前端 - 基础入门三大核心之JS篇㊲〗- DOM改变元素节点的css样式、HTML属性
- Java 算法篇-链表的经典算法:判断回文链表、判断环链表与寻找环入口节点(“龟兔赛跑“算法实现)
- 代码随想录二刷 | 链表 | 删除链表的倒数第N个节点
- 节点导纳矩阵
- bhosts 显示节点 “unreach“ 状态
- 电子电器架构 —— 车载网关边缘节点总线转换
- 〖大前端 - 基础入门三大核心之JS篇㊳〗- DOM访问元素节点
- 第四天||24. 两两交换链表中的节点 ● 19.删除链表的倒数第N个节点 ● 面试题 02.07. 链表相交 ● 142.环形链表II
- CS224W5.1——消息传递和节点分类
- Vue报错解决Error in v-on handler: “Error: 无效的节点选择器:#div1“
猜你感兴趣
版权申明
本文"「题解」环形链表的约瑟夫问题":http://eshow365.cn/6-37777-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!
- 上一篇: 卡码网语言基础课 | 11. 句子缩写
- 下一篇: transaction事务使用