规则: n 人围成一圈,按照顺序给标上 1 到 n 的序号;从 1 开始报数,报到 m 的人退出圈子,下一个人继续从 1 开始报数(m <= n);如此循环,一直到最后一人。
要求:输出每个人退出的顺序序号
例如
输入:n = 3 ,m = 1;
输出:3,1,2
核心:构造一个两倍长度的数组,首尾相接,模拟圆圈的情景
算法演示:
语言不好描述,看图吧,(建议结合程序一起看,更好理解)
void Game(int n, int m, int Sort[]) {
//重点:**两倍长度的数组**
int N[2*n];
for(int i = 0; i < n; i++) {
//初始化数组
if(i == 0) {
for(int j = 0; j < n; j++) {
N[j] = j+1;
N[j+n] = j+1;
}
}
else {
int a=m%(n-i+1);//报到 m 的人的下一个的位置,也就是下一次报数的开始
int New[n-i];//报到 m 的人退出后,新形成的序列
for(int j = 0; j < 2*(n-i+1); j++) {//**将 N 的部分数组传给 New**
if(j >= a && j < a+n-i ){
New[j-a] = N[j];
}
}
//记录 m 值
if(a!=0){
Sort[i-1] = N[abs(a-1)];
}
else{
Sort[i-1] = N[n-i];//特殊点,当 a=1时,(a-1)为负数
}
//使用 New 重新定义 N 前 2*(n-i)个值
for(int j = 0; j < n-i; j++) {
N[j] = New[j];
N[j+n-i] = New[j];
}
//下一次循环 n-i=0,程序将不再执行,于是在此处直接输出最后的 m 值
if(n-i==1){
out[i] = N[1];
break;
}
}
}
}