求:约瑟夫环(带路径) C语言程序
注意了:我需要的是时间复杂度为O(n)的程序 , 非O(n*m)
是一个数学的应用问题:
已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
例如:输入:n k m
输出 n个数 依次出列的编号
简单样例:9 1 5
5 1 7 4 3 6 9 2 8
如果是要O(n)的复杂度的话,那么直接使用数学解法得到递推公式:
令f[i]表示i个人报m退出最后留下者的编号,求f[n]
递推公式:
f[1]=0;
f[i]=(f[i-1]+m)%i; (i>1)
你这题多了一个起始偏移量k,那么就再变换一下,将f[n]的值变为 (f[n] - k ) % n就可以了。
#include<stdio.h>
main()
{
int n,k,m,i,h,a[],b[],c[];
n=scanf("%f",&f);
k=scanf("%f",&f);
m=scanf("%f",&f);
for(i=1;i<=n;i++)
{
a[i]=i;
}
for(i=1;i<=(n-1);i++)
{
if(n-1>m)
{b[i]=a[m];
for(h=1;h<=(m-1);h++)
{
a[h+n]=a[h];
}
for(h=1;h<=(m-1);h++)
{
a[h]=a[h+m];
}
}
elseif((n-1)==m)
{
b[i]=a[m]
}
else
{
for(h=1;(n-i+h)<=m;h++)
{
a[n-i+h]=a[h];
}
b[i]=a[m]
}
}
}
for(i=1;i<=n;i++)
{
printf("%c ",b[i]);
}
}