前段时间在逛百度的时候,发现了约瑟夫环这个算法;当时刚好忙完了,左右没事就花了点时间去研究了下这个算法,研究了才知道这算法还真点研究价值。
话说,在犹大人和罗马的战争期间,约瑟夫和其他40个犹大人反判者被罗马军队困在一个山洞中;这些犹大人反判者宁愿自己自杀也不想成为罗马的俘虏,于是他们站成了一个圆,从其中的某个人开始数每数到三就要被杀掉,直到所有人死光。但约瑟夫和他的一个朋友觉得自杀没意义,并不想死,于是他们很快就算出他和他朋友应该站在什么位置,使他们成为最后两个人,并最终活下来。
从上面的事件中我们可以知道两点信息:
1、人员的总数:40;
2、每次数到三的人都要被杀掉(数到数值):3; 好,现在我们就来解决这一题,然后写出成一个算法:
首先,我们先把每个人分配个编号,第一个数数的为1号,第二个为2号,以些类推一直到40号;然后我们可以慢慢排除要死掉的人,剩下的最后两位数就是我们最终的解(13,28)。
方法操作思路出来了,我们就可以对算法进行实现了,代码如下:
1 /// <param name="strArr">源数组(1-40)</param> 2 /// <param name="Num">数到几移除(3)</param> 3 /// <param name="StartNum">开始数(1)</param> 4 /// <returns></returns> 5 public ArrayList GetArrList(ArrayList strArr, int Num, int StartNum) 6 { 7 8 ArrayList ArrSource = new ArrayList(); 9 int nCount = 1; 10 int index = StartNum - 1; 11 while (strArr.Count > 0) 12 { 13 //数到移除数(3) 14 if (nCount == Num) 15 { 16 ArrSource.Add(strArr[index]); 17 strArr.Remove(strArr[index]); 18 nCount = 1; 19 } 20 else 21 { 22 nCount++; 23 index++; 24 } 25 //数到最后一个后回到每一个。 26 if (index == strArr.Count) 27 { 28 index = 0; 29 } 30 } 31 return ArrSource; 32 }
注:因在发现此算法时是在博客园 https://www.cnblogs.com/bg1qqc/p/8261837.html 发现的,所以算法中的代码会有所相似,固本人多写了别一种实现方式代码如下:
1 /// <param name="strArr">源数组</param> 2 /// <param name="Num">到几出移除</param> 3 /// <param name="StartNum">开始值</param> 4 /// <param name="nNumder"></param> 5 /// <returns>返回算法中的最后两位</returns> 6 public static ArrayList GetArrList(ArrayList strArr, int Num, int StartNum, int nNumder = 1) 7 { 8 int nCount = strArr.Count; 9 if (nCount == 2) 10 { 11 return strArr; 12 } 13 int index = 0; 14 for (int i = StartNum; i <= nCount; i++) 15 { 16 if (nNumder == Num) 17 { 18 //如要输出出列顺序数组,只需声明数组把移除的值依次增加到新声明数组中方可。 19 strArr.RemoveAt(index); 20 nNumder = 1; 21 } 22 else 23 { 24 index++; 25 nNumder++; 26 } 27 } 28 return GetArrList(strArr, Num, StartNum, nNumder); 29 }
如有不足或写错的地方欢迎指正,谢谢!!!!