请教一道C语言题目!
有N个人站成一圈,顺序排号,从第一个人开始报数(1到3),凡报到3的人退出圈子,问最后留下的是几号?
参考答案:在网上搜“Joseph问题”或“约瑟夫问题”等关键字,各种方法的代码一大堆。
解决的思路主要有两种,模拟方法和数学方法。
数学方法虽然理解起来比较难,但写出来简短高效,是真正学习编程的方向。
模拟方法中思路最自然的解法是用循环链表实现,但是这个方法实际效率比较低,当N很大或者报的数(题中的3)比较大时,就可能很慢。而且,很不幸地,这个方法写出来的程序也很长。
与用循环链表类似,也可以用一般的链表实现,思想和效果大同小异。
模拟方法的另一种思路是用数组来实现,数组的访问比较快,但它的麻烦之处在于数组的删除不方便,而且规模大时也比较慢。不过这个方法写出来的程序长度比用链表短得多(如果写得好的话)。
上面的程序好像在谭浩强的书上(或者是某数据结构的书?)就写了好几种。
下面的贴吧给出了多个模拟方法的代码,自己可以看。
这里也有一些
数学方法是给出关于这剩下的人数的一个递推公式。这个公式的详细描述和证明可以见Knuth等人写的《具体数学》头一章。或看中科大BBS上的文章:
下面给出数学方法的解答:
#include <stdio.h>
int main()
{
int n, m = 3, i, s=0;
printf ("N = ");
scanf("%d", &n);
for (i=2; i<=n; i++) s=(s+m)%i;
printf ("The winner is %d\n", s+1);
return 0;
}