约瑟夫环问题(变态杀人狂、围圈报数、猴子选大王等)有四种解题方法:
1、循环链表法 2、数组标记法 3、数组链接法 。这三种是基于模拟实现的,时间复杂度为O(n*m),当n和m取值很大时,效率低,比如m取100w时(数到100w才淘汰),即使只剩下了最后两个人,也要循环100w次才能出结果。
学计算机科学,一定要相信数学,它往往能带来惊喜,所以有了第4种实现方法:基于数学递推的方法,时间复杂度O(n)。思路:求n个人的结果,可以基于求n-1个人,求n-1个人时的结果,又可以基于求n-2个人,一直递推到求2个人、1个人时的情况。这就是递归的思路,但是递归在数据很大的时候开销成本也很高,因此我喜欢把递归都改写为循环来实现:
int ysf(int n,int m){ int i,s=0; for(i=2;i<=n;i++) s=(s+m)%i; return s+1; }