循环链表的约瑟夫问题描述
编号为 1 到 n 的 n 个人围成一圈。从编号为 1 的人开始报数,报到 m 的人离开。
下一个人继续从 1 开始报数。
n-1 轮结束以后,只剩下一个人,问最后留下的这个人编号是多少?
数据范围: 1 ≤ n,m≤10000
进阶:空间复杂度 O(1),时间复杂度 O(n)
示例一:
输入:5,2
返回值:3
说明:
开始5个人 1,2,3,4,5 ,从1开始报数,1->1,2->2编号为2的人离开 1,3,4,5,从3开始报数,3->1,4->2编号为4的人离开 1,3,5,从5开始报数,5->1,1->2编号为1的人离开 3,5,从3开始报数,3->1,5->2编号为5的人离开 最后留下人的编号是3
示例二:
输入:1,1
返回值:1
我们拿示例一做示范黑色为每个人的编号,有5个人,喊道2的人离场(绿色为该人的报道数),继续从一报数,直到剩一人为止。
最后只剩下编号为3 的人。
解题思路:
1.创建一个循环链表,每个节点上的值就为其节点的编号。
2.创建循环过程,用一个count作为计数器,当count==m时,实行链表节点删除,直到剩下一个人为止。
代码
typedef struct SListNode {int val;struct SListNode*next;
}SLNode;SLNode* BuyNode(int i)//创建节点
{SLNode* tmp=(SLNode*)malloc(sizeof(SLNode));if(tmp == NULL){perror("malloc fail!\n");exit(1);}tmp->val = i;//i就是链表节点的编号tmp->next = NULL;return tmp;
}
SLNode* CreatList(int n)//创建n个节点的环形链表
{SLNode* phead = BuyNode(1);SLNode* ptail = phead;for(int i = 2;i <= n; i++){SLNode* pcur=BuyNode(i);ptail->next= pcur;ptail= ptail->next;}//联成环ptail->next=phead;return ptail;//后续需要尾节点和头节点
}int ysf(int n, int m ) //主体函数
{SLNode* prev=CreatList(n);SLNode* pcur=prev->next;int count=1;while(pcur->next!=pcur)//最后只剩一个人,pcur->next=pcur{ if(count == m){//count=m,实施链表节点的删除SLNode* next=pcur->next;prev->next= next;free(pcur);pcur=next;count = 1;}else{prev = pcur;pcur = pcur->next;count++;}}
//返回最后编号return pcur->val;
}
这个博客如果对你有帮助,给博主一个免费的点赞就是最大的帮助❤
欢迎各位点赞,收藏和关注哦❤
如果有疑问或有不同见解,欢迎在评论区留言哦❤
后续我会一直分享双一流211西北大学软件(C,数据结构,C++,Linux,MySQL)的学习干货以及重要代码的分享