已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列(这就是约瑟夫环问题)
如何解决:我第一时间想到的是用环形链表。假设有N人,报的数为M,则第一次第一个人为头,则第M人出列,接着以M+1为头,(M+1+M)淘汰,在还剩一个人之前,循环下去。链表实现就是在链表内报数,出列的指针指向空,前一个指向他的指针指向他原本指向的下一个结构体。因为每个人要报数M次,所以时间复杂度为O(N*M)
代码实现:
#include<stdio.h>
#include<stdlib.h>
struct Monkey
{
int m;
struct Monkey *next;
};
int main()
{
int n,i;
int key;
scanf("%d",&n);
struct Monkey monkey[n];
struct Monkey *wang,*temp,*p;
wang=&monkey[0];
for(i=0;i<n;i++) //构造环形链表
{
monkey[i].m=i+1;
if(i<n-1)
monkey[i].next=&monkey[i+1];
else
monkey[n-1].next=&monkey[0];
}
scanf("%d",&key);
while(n!=1)
{
for(i=1;i<key;i++) //报数
{
p=wang;
wang=wang->next;
}
temp=wang; //出列
wang=wang->next;
temp->next=NULL;
p->next=wang;
n--;
}
printf("%d",wang->m);
}