击鼓传花

击鼓传花的规则:
几个朋友一起玩一个游戏, 围成一圈, 开始数数(数数时数字都是挨着的,第一个人数1,之后的人数2), 数到某个数字的人自动淘汰。汰的人后面再从1开始数,重复上面的游戏,直到就剩下一个人,请问剩下了谁?

  1. // 测试例子
  2. var names = ["John", "Jack", "Camila", "Ingrid", "Carl"];
  3. var endName = passGame(names, 8); // 数到 8 的人淘汰
  4. console.log("最终留下:" + endName); // 'john'

实现

function passGame (names, n) {
    let count = 1;
    while (names.length > 1) {
        let cur = names.shift();
        if (count != 0) {
            names.push(cur);
        }
        count++;
        count %= n;
    }
    return names[0];
}

console.log(passGame(["John", "Jack", "Camila", "Ingrid", "Carl"], 8)) // John

image.png

约瑟夫问题

剑指 Offer 62. 圆圈中最后剩下的数字

循环队列, 超时

var lastRemaining = function(n, m) {
    let arr = Array.from({length: n}, (v, i) => i);
    let count=1;
    while (arr.length > 1) {
        let cur = arr.shift();
        if (count % m != 0) {
            arr.push(cur)
        }
        count++;
    }
    return arr.pop();
};

递归实现

var lastRemaining = function(n, m) {
    return helper(n, m);
};

function helper(n, m) {
    if (n == 1) return 0;
    return (helper(n-1, m) + m) % n;
}

85+35

非递归实现

var lastRemaining = function(n, m) {
    let k = 0;
    for (let i=2; i<=n; i++) {
        k = (k+m)%i;
    }
    return k;
};

40+83