约瑟夫环
约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
n=总人数, k=开始报数, m=数到出列
实例1:
有17个人围成一圈(编号0~16),从第0号的人开始从1报数,凡报到3的倍数的人离开圈子,然后再数下去,直到最后只剩下一个人为止,问此人原来的位置是多少号?
Code A :一般方法,用数组来模拟过程
static void JosephusA() { int[] ren = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; var j = 17;//还在的人数 var h = 0;//下标 var k = 1;//到三出圈计数 while (j != 1)//只有一个人时结束循环 { if (h == 17) h = 0;//下标超出就置0,围成圈 if (ren[h] == 1 && k == 3) { ren[h] = 0; k = 1; j--; } else { if (ren[h] == 1) { k++; } } h++; } for (int z = 0; z < 17; z++) { if (ren[z] == 1) { Console.WriteLine("N={0}", z); } } }
N=10
Code B: 数学法
static void JosephusB(int n, int k, int m) { int index = k; for (int i = 2; i <= n; i++) { index = (index + m) % i; } Console.WriteLine(index); }
Code C: 链表法
public static void JosephusC(int n, int k, int m) { /* *已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。 *从编号为k的人开始报数,数到m的那个人出列; *他的下一个人又从1开始报数,数到m的那个人又出列; *依此规律重复下去,直到圆桌周围的人全部出列。 */ Link head = new Link() { Value = "1" }; Link node = head; for (int i = 2; i <= n; i++) { node.Next = new Link(); node = node.Next; node.Value = i.ToString(); } node.Next = head; //循环链表建立完毕 Link cur = head; //指针移动到第K个人 for (int i = 1; i < k; i++) { cur = cur.Next; } //开始报数 do { for (int i = 1; i < m - 1; i++) { cur = cur.Next; } //Console.WriteLine(cur.Next.Value); cur.Next = cur.Next.Next;//删除第m个人 cur = cur.Next;//指针指向m+1 } while (cur != cur.Next);//仅剩下一个人,报数结束 Console.WriteLine(cur.Value); } /// <summary> /// 循环链表节点 /// </summary> public class Link { public string Value; public Link Next; }
|
优点 |
缺点 |
应用场景 | |
| Code A |
|
|
|
| Code B |
|
|
|
| Code C |
|
|
|
