算法笔记_029:约瑟夫斯问题(Java)
目錄
1 問題描述
2 解決方案
?
1 問題描述
引用自《算法設計與分析基礎》第三版:
約瑟夫斯問題,是以弗拉瓦斯。約瑟夫斯(Flavius Josephus)的名字命名的。約瑟夫斯是一個著名的猶太歷史學家,參加并記錄了公元66—70年猶太人反抗羅馬的起義。約瑟夫斯作為一個將軍,設法守住了裘達伯特的堡壘達47天之久,但在城市陷落了以后,他和40名頑強的將士在附近的一個洞穴中避難。在那里,這些反抗者表決說“要投降毋寧死”。于是,約瑟夫斯建議每個人應該輪流殺死他旁邊的人,而這個順序是由抽簽決定的。約瑟夫斯有預謀地抓到了最后一簽,并且,作為洞穴中的兩個幸存者之一,他說服了他原先的犧牲品一起投降羅馬。
?
上述是約瑟夫斯問題的起源,看完后個人感覺有點抽象,其實約瑟夫斯問題的本質為:n個人(編號由?1,2,?...,?n)圍成一圈,由編號為1的人從1開始報數,報到k的退出自殺,剩下的人繼續從1開始報數,直到圈內只剩余1人,求勝利者的編號。(n>0, k>0)??
例如:
原n個人編號:
1 ?2 ?3 ?4 ... ... n-1 ?n
現在進行報數:
1 ?2 ?3 ?4... k(出列自殺) ?1 ?2 ?...(循環報數,當到達編號為n的人時,下一個報數的從編號為1的人開始進行)
?
?
2 解決方案
約瑟夫斯問題的核心即找出給定n個人從前到后的自殺順序,最后一個將要進行自殺的人即為幸存者。
具體編碼如下:
package com.liuzhen.chapter4;import java.util.Scanner;public class JosephProblem {/** 參數n:給定總人數* 參數k:報數為k的人出列* 函數功能:返回n個人從前到后的自殺順序*/public int[] getKillOrder(int n,int k){int[] result = new int[n];int[] man = new int[n];for(int i = 0;i < n;i++)man[i] = i+1; //給n個人編號,編號分別為1~nint count = 0; //用于計算當前已經自殺的人數int pos = -1; //用于記錄遍歷數組man當前下標int tempK = 0; //用于計算報數大小,一旦tempK = k,則喊到k的人出列while(count < n){pos = (pos+1)%n; //遍歷過程中,會出現環列,取余可以除去環的影響if(man[pos] != 0) //man[pos] == 0,表示此人已自殺tempK++;if(tempK == k){result[count++] = man[pos]; //記錄當前自殺人的編號man[pos] = 0;tempK = 0;}}return result;}public static void main(String[] args){JosephProblem test = new JosephProblem();Scanner in = new Scanner(System.in);System.out.println("請輸入約瑟夫斯問題的總人數n:");int n = in.nextInt();System.out.println("請輸入約瑟夫斯問題的報數設定值k:");int k = in.nextInt();int[] result = test.getKillOrder(n,k);System.out.println("共"+n+"人,依次報數,當報到"+k+"的人自殺,其自殺順序為:");for(int i = 0;i < result.length;i++)System.out.print(result[i]+" ");} }運行結果:
請輸入約瑟夫斯問題的總人數n: 6 請輸入約瑟夫斯問題的報數設定值k: 2 共6人,依次報數,當報到2的人自殺,其自殺順序為: 2 4 6 3 1 5 請輸入約瑟夫斯問題的總人數n: 7 請輸入約瑟夫斯問題的報數設定值k: 2 共7人,依次報數,當報到2的人自殺,其自殺順序為: 2 4 6 1 5 3 7 請輸入約瑟夫斯問題的總人數n: 10 請輸入約瑟夫斯問題的報數設定值k: 3 共10人,依次報數,當報到3的人自殺,其自殺順序為: 3 6 9 2 7 1 8 5 10 4?
參考資料:
? ? ?1.簡單的約瑟夫環算法
總結
以上是生活随笔為你收集整理的算法笔记_029:约瑟夫斯问题(Java)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UEFI Shell 常用命令
- 下一篇: java美元兑换,(Java实现) 美元