class Joseph {
  public:
    int getResult(int n) {
        if (n == 1) return 1;//如果是一个人,直接输出
        queue<int> myqueue;
        for (int i = 1; i <= n; ++i) { //编号入队
            myqueue.push(i);
        }
        int j = 2;
        while (myqueue.size() > 1) {
            int count = myqueue.size(); //count很关键,注意到在队列的时刻变化中,myqueue.size()是一个动态变化的值
            //必须保证接下来的循环次数固定为一开始的队列长度,且每次while循环时都需要更新,因此要放到while里面
            for (int i = 1; i <= count; ++i) {
                if (i % j == 1)
                    myqueue.push(myqueue.front());
                myqueue.pop();
            }
            j++;
            //第二轮再从上一轮最后一个报数的人开始依次报数,因此给队列循环一下,把最后一个放到队首
            //本题中n有奇偶数之差别,奇数状态下每次最后的那位是“最后一人”,但是偶数不是
            //偶数情况下,第一次循环一定是最后一位偶数需要出队,则最后一人实则为倒数第二位
            //这种情况处理比较麻烦,干脆直接让他们完全循环一遍,然后调整位置
            for (int i = 0; i < myqueue.size() - 1; ++i) {
                myqueue.push(myqueue.front());
                myqueue.pop();
            }
        }//while
        return myqueue.front();
    }
};

约瑟夫问题②

用queue实现循环队列,全部出队,符合条件就放到队尾,本期需要注意的是“最后一人”的处理办法。尝试了一会发现用这种循环队列的办法不好处理,写法很复杂,我直接不处理他,干脆再循环一次队列把最后一位放到队首。

具体看代码