Josephus problem kill
阿新 • • 發佈:2017-11-18
public 返回 程序 true pri 約瑟夫環問題 .com 部分 這樣的
方便求解最後的勝利者同時也適合打印 出列 序列的,時間復雜度O(N).
下面方法借鑒自Java程序練習-約瑟夫環問題
public static int josepusONWithList(int n, int m) { return josepusONWithList(n, m, 1); } public static int josepusONWithList(int n, int m, int k) { if (n <= 0 || m <= 0 || k <= 0) return -1; LinkedList<Integer> list = new LinkedList<Integer>(); for (int i = 1; i <= n; i++) list.add(i); int outPos; while (list.size() > 1) { outPos = (int) (k + m - 2) % list.size(); // System.out.print(list.get(outPos)+" , "); list.remove(outPos); k = outPos + 1; } // System.out.println(list.get(0)); return list.get(0); }
在有時候需要知道出列的序列,上述System.out部分就是出列序列
首先我們通過思考可以得到一個很顯然的結論,n個人時的獲勝者和這n個人淘汰掉一個人繼續遊戲下的獲勝者一定是同一個人。(有點像廢話...)所以如果我們能確定 n-1個人時候的獲勝者也就可以得到 n 個人時候的情況,因為兩者的排列存在一種對應關系。 考慮n = 6 m = 3的情況 0 1 2 3 4 5 3 4 5 0 1 2 可以很明顯的看出上下兩行存在著 + m 模 n的對應關系。 這樣這個問題就可以通過遞推的方式解決了, f[i] 為 場上有 i 個人時,最後獲勝者的編號(從零開始)。 那麽就存在著這樣的遞推式 f[i] = ( f[i-1] + k ) % i 我們還可以知道 f[1] = 0 所以可以通過這個遞推式輕松的得到答案啦~public static int josephusON(int n, int m) { return josephusON(n, m, 1); } /** * Josephus 環的一個O(N)算法 * * @param n 總人數 * @param m 數到m的人出列 * @param k 開始報數人的編號 * @return 最後一個出列的編號 */ public static int josephusON(int n, int m, int k) { int p = 0; for (int i = 2; i <= n; i++) { // System.out.print((p + k == n ? n : (p + k) % n)+" "); p = (p + m) % i; } return (p + k) % n; // 返回最後一人的編號 }
Josephus problem kill