特别强调:这一篇适合与刚刚学数据结构的uu们,因为我就是才开始学就遇上了老师布置的这道题 所以写下了这篇blog记录一下 希望你们也能看懂哦~
约瑟夫环问题:任给正整数N和K,按下述方法可以得到1,2, …,N的一个置换,将数字1,2,…,n环形排列,按顺时针方向自1开始报数,报到K时输出该位置上的数字,并使其出列。然后从他在顺时针方向的下一个数字继续报数,如此下去,直到所有的数字全部出列为止。例如N=10,K=3,则正确的出列顺序应为3,6,9,2,7,1,8,5,10,4。
分析过程:
把约瑟夫环看作一个圈圈⭕️ 首尾相连 为了遍历所有的数字 则利用while循环。
用数组给每个数字标记为0,如果一个数字列出则标为1 一个一个出圈 直到所有的数字由标记0到1为止。number用来计数出圈的人数 当number与N个数相等的时候 while循环结束~
因为数到K的那个数字就要出圈,所以需要index计算1~K的下标。当index == K时,数字就出圈了,顺便标记为1,即arr[c] = 1。
大体过程就是这样了....
注意⚠️的是 这个特殊情况 在最后的数字仅剩下4的时候时 循环内的c已经超过了N,所以要设置条件if(c > N) c = 1;使arr[c]从新开始查找标记为0的数字,直到条件满足的时候标记为1,出圈。
如果还是不太清楚的话 可以尝试自己画画哦~(大概就这样子)
int arr[11] = {0};//标记大家都是0
void test()
{
int N,K; //N为从1开始到n K为K个K个的数
cout<<"input N:";
cin>>N;
cout<<"input K:";
cin>>K;
int c=0;
int number = 0;//number为出圈的人数
int index = 0;//index为报数人的标号 从1~K
while(number!=N)
{
c++; //c为当前人数的编号 也就是输出从1~n
if(c>N){c=1;} //特殊情况
if(arr[c] == 0)//大家都还没有出圈的时候 标记为0
{
index++;
//k表示当前这个编号为c的人报数为k
if(index == K)
{
arr[c] = 1;
//标记为1 此数出圈
number++;
cout<<c<<" ";
index=0;
//重制标号
}
}
}
}