小孩报数问题(约瑟夫环)

文章目录

  • 1 问题描述
  • 2 数组模拟法
  • 3 递推公式法
  • 4 环形链表法

1 问题描述

有30个小孩,编号从1-30,围成一圈依次报数1、2、3,数到3的小孩退出这个圈,然后下一个小孩重新报数1、2、3,问最后剩下的那个小孩的编号是多少?

2 数组模拟法

function childNum(num, count) {
    let total = [];
    for (let i = 0; i < num; i++) {
        total[i] = i + 1;
    }
    let exitCount = 0;
    let counter = 0;
    let curIndex = 0;
    while (exitCount < num - 1) {
        if (total[curIndex] != 0) {
            counter++;
        }
        if (counter == count) {
            counter = 0;
            exitCount++;
            total[curIndex] = 0;
        }
        curIndex++;
        if (curIndex == num) {
            curIndex = 0;
        }
    }
    for (let i = 0; i < num; i++) {
        if (total[i] != 0) {
            return total[i];
        }
    }
}
console.log(childNum(30, 3)); //29

3 递推公式法

  • 约瑟夫环递推公式:f(n, m) = (f(n - 1, m) + m) % n。
  • 在n个人中,每次报到m的人出圈,最后存活的人的编号为f(n, m)。
function josephusMath(num, count) {
    let last = 0; // 初始化最后存活的人的编号(从0开始),只有一个人时,存活编号为0
    for (let i = 2; i <= num; i++) {
        last = (last + count) % i; // 递推公式
    }
    return last + 1; // 返回从1开始的编号
}

console.log(josephusMath(30, 3)); // 输出最后存活的人的编号

4 环形链表法

…未完待续

你可能感兴趣的:(前端面试,javascript,前端,开发语言)