循环队列 解Josephus环 游戏

孩提时的你是否玩过“烫手山芋”游戏:一羣小孩围成一圈,有一个刚出锅的山芋在他们之间传递。其中一个孩子负责数数,每数一次,拿着山芋的孩子就把山芋转交给右边的邻居。一旦数到个特定的数,拿着山芋的孩子就必须退出,然后重新数数。如此不断,最后剩下的那个孩子就是

幸运者。通常,数数的规则总是从 1 开始,数到 k 时让拿着山芋的孩子出列,然后重新从 1 开始。 Josephus问题可以表述为: n 个孩子玩这个游戏,最后的幸运者是谁?

为了解答这个问题,我们可以利用队列结构来表示围成一圈的n个孩子。一开始,假定对应于队列首节点的那个孩子拿着山芋。然后,按照游戏的规则,把“土豆”向后传递到第k个孩子(交替进行k次dequeue()和k次enqueue()操作),并让她出队( dequeue())。如此不断迭代,直到队长( getSize())为 1 。

*
    Josephus环 游戏
 */
public class Josephus {
    public static Object josephus(Queue<String> q, int k) {
        if(q.isEmpty()) return null;
        while (q.size() > 1) {
            System.out.println(q.toString());
            for (int i = 0; i < k; i++) {
                q.add(q.poll());
            }
            String e=q.poll();//数到第K个数的人退出
            System.out.println("\n\t" + e + "退出");
        }
        return q.poll();
    }
    public static Queue<String> build(String arr[]) {
        Queue<String> q = new LinkedList<>();
        Collections.addAll(q, arr);
        return q;
    }
    public static void main(String[] args) {
        String[] kid = {"Alice", "Bob", "Cindy", "Doug", "Ed",
                "Fred", "Gene", "Hope", "Irene", "Jack",
                "Kim", "Lance", "Mike", "Nancy", "Ollie"};
        System.out.println("最终的幸运者是" + josephus(build(kid), 5));
    }
}

点赞