問題ジョセフは何ですか
有名なユダヤ人の歴史家ヨセフスは、次の物語を持っていたと言われて:Qiaotapate、39人のユダヤ人とヨセフスと彼の友人が洞窟に隠れ、ローマ占領した後、39人のユダヤ人は、むしろ死んでしまう決めて、敵を巻き込まないでくださいそして自殺、円形に配置された41人の個人、最初の個人的なCountinを決め、すべての3番目の数字は、すべての自殺まで、新聞による再カウント、その後、自殺を持っている人に報告しましたこれまでに死亡しました。しかし、ヨセフスと彼の友人は従わたくありませんでした。個々のk-2(最初の男が逆になっているため)を超えて、人と起動し、k個の個人を殺します。次に、K-1、次いで、個々の上、及びk番目の個体を殺します。最終的には唯一の次の人は残すようになるまでのプロセスは、円の周り続けて、この人は生き続けることができます。問題は、与えられたと、実行を避けるために、どこかに立って始めて、ということでしょうか?
ヨセフの物語残酷比較し、以下のように、私たちは少しゲームを変えたヨセフの問題は、ゲームのルールは以下のとおりです。
手の円を手に、番号1,2,3 ... n個の個別のリビングを想定、パケット数の合意された数k(1 <= K <= N)彼の、m個のターンのうち人の数、始まりました1と下部オフ番号、からm個の環のうちの人々の数など、残りの1つは、それにより円のシーケンス番号を生成し、勝者になるまで、
アナログの周りに座って、n個の個人を使用して循環リスト
まず、我々はそれによって、n個の円に座って個人をシミュレートし、循環リンクリストを定義します。以下の単鎖実装コードの下に見て
1 / * 2 *一方向循環リスト 3。 * / 4。 クラスCycleSingleLinkedList { 5。 PersonalNodeまず= NULL ; 6 / ** 。7 * NUM循環リストにノードを追加します 。8 * @paramのNUM 。9 * / 10 公共 ボイド追加(INT NUM){ 11。 IF(NUM <1。){ 12は System.out.printf( "無効なパラメータ" ); 13である 返す; 14 } 15 PersonalNode CURR = NULL; 16 のためには、(int型 1 = Iを、I <= NUM; iは++ ){ 17 PersonalNode personalNode = 新しいPersonalNode(I)。 18 もし(I == 1 ){ 19 // 添加第一个节点 20 第= personalNode。 21 CURR = 最初; 22 curr.setNext(最初の); 23 } 他{ 24 curr.setNext(personalNode)。 25 (第一)personalNode.setNext。 26 CURR = personalNode; 27 } 28 } 29 30 } 31 32 } 33 34 /** 35 * 人物节点 36 */ 37 class PersonalNode { 38 private int no; 39 private PersonalNode next; 40 41 public PersonalNode(int no){ 42 this.no = no; 43 } 44 45 public int getNo() { 46 return番号; 47 } 48 49 公共 ボイド(setNo INT なし){ 50 この .NO = いいえ。 51 } 52 53 公衆PersonalNode getNextを(){ 54 リターン次。 55 } 56 57 公共 ボイドsetNext(PersonalNode次){ 58 この .next = 次回。 59 } 60 }
我々は最初のノードを作成するときにプロセスの凡例は円形のリストをn個のノードを追加する方法を説明下に形成するために、我々は、第1のノードと次電流に第1ノード点に第一及び現在のポイントを聞かせてループ。第2のノードを追加する場合、次のように最初に第2のノード次に、第二の電流ノードへのポインタであり、そして第2のノードへの電流、すなわち、現在のポイントを移動します。
今では私たちの問題解決のn kの第二段階から次の番号を達成するために、一緒に座って個人が少数の個人を始めた最初のステップです。第二のステップは、K-1回、人々の数の最初の数を作ることにより、最初のポインタように、すなわち第一のポインタが移動され、比較的簡単です。しかし、ノードのうち最初のラップには円形のリストであるため、次のポインタは、第1のヘルパー(に等しくなるまで、我々はそのようにサイクルを最初にヘルパーポインタポイントせまず、すなわち、ノードの前に第一のポインタをポイントするようにヘルパー・ポインタを定義し、必要性を指摘)。そして、常に最初のノードのポインタ(最初のノードと同じノードへのポインタ)の前にヘルパーポインタを保持します。即ち、K = 2を想定している第二の個体から始まるの数、M = 3、すなわち、図に示すようにリング3のうち人の数、。
この時点で第一次ヘルパー次に等しくなるように、円をノード4、その後、図3に示すように、第一次のヘルパーが等しいせ人を見つけます。
ノード1は、開始番号、番号3、すなわちノード3円、図のケースへのポインタとして、この時点から継続します。
次の環の環をノード3の後にノード1であり、そして第1のヘルパーへのポインタと同じノード、すなわち、ノード2までのサイクルは、円への最後のものです。コードは以下の通りです
1 /** 2 * 约瑟夫问题 3 * @param n n个人围成圈 4 * @param k 第k个人开始报数 5 * @param m 数到m的人出圈 6 */ 7 public void joseph(int n,int k,int m){ 8 //添加n个人 9 add(n); 10 //helper指针指向first的前一个节点 11 PersonalNode helper = first; 12 while (helper.getNext() != first){ 13 helper = helper.getNext(); 14 } 15 //找到第k个人 16 for (int i = 0; i < (k-1); i++) { 17 first = first.getNext(); 18 helper = helper.getNext(); 19 } 20 //数到m的人出圈 21 while (true){ 22 if(helper == first){ 23 break; 24 } 25 for (int i = 0; i < (m-1); i++) { 26 first = first.getNext(); 27 helper = helper.getNext(); 28 } 29 System.out.printf("编号为%d的人出圈\n",first.getNo()); 30 first = first.getNext(); 31 helper.setNext(first); 32 } 33 System.out.println("最后出圈的人是:"+first.getNo()); 34 35 }
测试代码
1 public static void main(String []args){ 2 CycleSingleLinkedList linkedList = new CycleSingleLinkedList(); 3 linkedList.joseph(4,2,3); 4 }
测试结果:
总结
以上就是实现约瑟夫问题的循环链表解决思路,当然肯定还有很多别的解决思路,欢迎留言探讨,谢谢。