1. 程式人生 > >Josephus problem kill

Josephus problem kill

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