文章目录
- 问题描述
- 测试用例
- 代码
- 思路
问题描述
约瑟夫问题是一个经典的问题。已知 n 个人(不妨分别以编号 1,2 ,3,…,n 代表 )围坐在一张圆桌周围,从编号为 k 的人开始,从1开始顺时针报数 1, 2, 3, ...,顺时针数到m 的那个人,出列并输出。然后从出列的下一个人开始,从1开始继续顺时针报数,数到 m的那个人,出列并输出,…依此重复下去,直到圆桌周围的人全部出列。
输入:n, k, m
输出:按照出列的顺序依次输出出列人的编号,编号中间相隔一个空格,每10个编号为一行。
测试用例
测试输入 | 期待结果 | |
测试用例 1 | 9,3,2 | 4 6 8 1 3 7 2 9 5 |
测试用例 2 | 10,12,3 | k should not bigger than n. |
代码
#include <stdio.h>
#include <stdlib.h>
struct node
{
int x;
struct node* next;
};
int main()
{
int n,k,m;
int i,j,l;
scanf("%d,%d,%d",&n,&k,&m);
while(1)
{
if(n<1||k<1||m<1)
{
printf("n,m,k must bigger than 0.\n");
break;
}
if(k>n)
{
printf("k should not bigger than n.\n");
break;
}
struct node *head,*p,*out;
head=(struct node*)malloc(sizeof(struct node));
head->x=-1;
head->next=head;
for(i=n;i>0;i--)
{
p=(struct node*)malloc(sizeof(struct node));
p->next=head->next;
p->x=i;
head->next=p;
}
while(p->next!=head)
{
p=p->next;
}
p->next=head->next;
p=p->next;
for(i=0;i<k-2;i++) p=p->next;
for(j=1;j<=n;j++)
{
for(l=0;l<m-1;l++) p=p->next;
out=p->next;
p->next=out->next;
printf("%d",out->x);
free(out);
if((j==n)||(j%10==0))
printf("\n");
else
printf(" ");
}
break;
}
return 0;
}
思路
创建一个循环单链表,然后从head开始寻找第m个人,即每次走m-1次,找到m的节点,输出m后将其从链表中删除。重复执行以上操作直到链表中只剩head节点。