文章目录
- 前言
- 1.题目
- 2.解题思路
- 2.1创建节点
- 2.2.创建环形链表
- 2.3.进行遍历
- 4参考代码
前言
前段时间我们学习到了单链表和双向链表的相关知识,下面我们解决一道具有代表性的一个编程题。
牛客网—环形链表的约瑟夫问题
1.题目
2.解题思路
2.1创建节点
//创建节点
ListNode *LTByBode(int n)
{ListNode *newnode= (ListNode*)malloc(sizeof (ListNode));newnode->val=n;newnode->next=NULL;return newnode;
}
2.2.创建环形链表
//创建环形链表
ListNode *circleList(int x)
{ListNode *phead= LTByBode(1);ListNode *ptail=phead;for(int i=2;i<=x;i++){ptail->next= LTByBode(i);ptail=ptail->next;}//现在到了最后一个节点,然后首尾相连ptail->next=phead;return ptail;
}
2.3.进行遍历
1.首先要使用cnt进行计数,每走一步记录一次,开始的时候cnt=1。
还要创建两个指针,分别指向环形链表的第一个最小值(prev)和第二个最小值(pcur=prev->next)
2.如果cnt!=m,那么两个指针都往后走,cnt+1.
3.如果cnt==m,那么,先将prev的下一个指针,指向pcur的下一个指针(prev->next=pcur->next)。然后释放掉pcur,其次pcur也要往后移动(pcur=pcur->next),cnt恢复到默认值(cnt=1)。
4.循环的停止条件是pcur的下一个指针指向了自己(pcur->next=pcur)。
int ysm(int n,int m)
{ListNode *prev= circleList(n);ListNode *pcur=prev->next;int cnt=1;while (pcur->next!=pcur){if(cnt==m){prev->next=pcur->next;free(pcur);pcur=prev->next;cnt=1;}else {prev=pcur;pcur=pcur->next;cnt++;}}return pcur->val;
}
4参考代码
/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param n int整型 * @param m int整型 * @return int整型*/#include <stdlib.h>
typedef struct ListNode Listnode ;//创建节点Listnode* SLTByNode(int x){Listnode* tmp=(Listnode*)malloc(sizeof(Listnode));tmp->next=NULL;tmp->val=x;return tmp;}//创建循环链表Listnode* CreateCircle(int x){//先创建第一个字节Listnode*phead=SLTByNode(1);Listnode*ptail=phead;for(int i=2;i<=x;i++){ptail->next=SLTByNode(i);ptail=ptail->next;}//首尾相连,形成循环ptail->next=phead;return ptail;}
int ysf(int n, int m ) {// write code hereListnode* prev=CreateCircle(n);Listnode*pcur=prev->next;int cnt=1;while(pcur->next!=pcur){if(cnt==m){//销毁pcurprev->next=pcur->next;free(pcur);pcur=prev->next;cnt=1;}else {//不需要销毁prev=pcur;pcur=pcur->next;cnt++;}}return pcur->val;
}
完