n个人围成一圈,顺序排号,从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来几号的那位

思考:1、围成一圈?怎么围?

2、退出圈子?怎么实现。

3、怎么判断最后留下的是几号?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <stdio.h>
int main()
{
int n; //总人数
scanf("%d", &n);
int a[100];
for (int i = 0; i < n; i++) //顺序排号
{
a[i] = i + 1
}
int k = 0; //报数
int m = 0; //记录退出圈子的个数
int last;
for (int i = 0; i < n; i++) {
if (a[i] != 0) //除去为0的
{
k++; //报数
}
if (k == 3) //报到3退出,
{
a[i] = 0; //赋值为0,代表退出圈子;
m++; //记录一个退出
k = 0; //重新将k赋值,下次重新报数到3
}
if ((n - m) == 1) //当剩最后一人的时候,结束循环
{
for (int j = 0; j < n; j++) {
if (a[j] != 0) {
last = a[j];
}
}
break;
}
if (i == (n - 1)) //围成一圈,无限循环
{
i = -1; //当循环到最后一个时,将i重新赋值到第一个.因为会执行一次i++,所以要赋值为-1,否则会跳过第一个.
}
}
printf("%d", last);
return 0;
}

1、围成一圈需实现的结果就是当最后一人报数过后,到第一人报数。根据需求,列出循环,判断当循环到最后一个人的时候,重新赋值循环变量,使其重新循环到第一人。

注意:这将会导致无限循环,需想办法跳出循环。将循环变量重新赋值后,还会执行i++,再而才会进行循环条件判断,是否继续进行循环。所以要时i++后的值,指向第一个人,即i==0,所以i应赋值为-1。否则将会跳过第一个人执行循环体。

2、退出圈子,需实现的需求就是下次报数不再进行报数,或许会想到删除,将报到3的人踢出圈子,不过数组实现删除却有些麻烦,或者换成链表组成圈子,实现删除操作将会简单很多。嗯》》》不如换个思考方式,报到3的人,为他做一个标记,循环报数对有标记的人就不用报数。虽并未实际“退出圈子”,却也实现了需求。对于问题的实际需求,需灵活判断。找到效率更高的算法。

3、对一圈的人,顺序排序,当退出的人(标记的人)达到总人数减一的时候,也就是只剩下一人的时候,循环全部人,查找其中未被标记的输出即可。

动画演示

–c

动画也太难搞了吧。https://www.xiuzhan365.com/video-99031225.html