一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。请问是原来第几号猴子当选猴王?
输入格式:
输入在一行中给一个正整数N(≤1000)。
输出格式:
在一行中输出当选猴王的编号。
输入样例:
11
输出样例:
7
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
if (n == 1) {
printf("%d\n", n);
return 0;
}
int arr[1000] = {0}; //定义数组,空间大小就给猴子最多的情况,1000,都赋初始值0
for (int i = 1; i <= n; ++i) { //根据输入的值,有多少只猴子,就把多少个元素改成1
arr[i] = 1;
}
int a = 0; //用于计数淘汰猴子的数量
int b = 0; //记录报数的次数,用于计算 b%3
int j = 1; //定义下标
while (a<(n-1)) //这里因为要留一只猴子,所以淘汰猴子数得小于猴子总数减一
{
if (arr[j] == 0) { //这里思路关键点,和下面的if 是思路关键点,如果此下标数组的值为0,则跳过
j++;
if (j == (n+1) ) { //判断是不是最后一只猴子,如果本轮结束,继续从1开始报数
j = 1;
}
continue;
}
b++;
if (b%3 == 0) { //如果报数的是3的倍数,则淘汰,改下标元素赋值为0
arr[j] = 0;
a++; //记录淘汰个数
}
j++;
if (j == (n+1) ) {
j = 1;
}
}
for (int k = 1; k <= n; ++k) {
if (arr[k] == 1) {
printf("%d\n", k); //得到仅剩的猴子
}
}
return 0;
}
一开始想的用循环链表,但是发现循环链表也不怎么好实现。于是用数组实现。总体思路就是创个数组,每个元素代表一直猴子,给所有猴子一个黄牌(代码赋值为1),然后报数为3倍数的猴子,将黄牌换成红牌(重新赋值为0)但是不离场,继续报数,当第二轮报数时,如果遇到拿红牌的猴子(值为0的元素),则跳过。一直循环直到剩下一只猴子。