题目:有一个数组a[N]顺序存放0~N-1,要求每隔两个数删掉一个数,到末尾时循环至开头继续进行,求最后一个被删掉的数的原始下标位置。以8个数(N=7)为例:{0,1,2,3,4,5,6,7},0->1->2(删除)->3->4->5(删除)->6->7->0(删除),如此循环直到最后一个数被删除。
输入:
每组数据为一行一个整数n(小于等于1000),为数组成员数,如果大于1000,则对a[999]进行计算。
输出:
一行输出最后一个被删掉的数的原始下标位置。
这道题是一个约瑟夫环问题,有特定的公式推导,公式的最后结果是:
f(n,m)=(f(n-1,m)+m)%n
可以看下面这张表:
当n=10,先死掉的是索引为2的数,接下来数组长度变为9,死掉的是索引为2的数,依次直到n=1,存活的是索引为0的数d,那么我们再看看d每次存在的位置
有f(10)=3,f(9)=0,f(8)=6...f(2)=1,f(1)=0 ,对比f(10)和f(9),可以得到(f(9)+3)%10 = f(10),可以推导出f(n,m)=(f(n-1,m)+m)%n
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
})
var arr = []
rl.on('line', (line) => {
var num = Number(line.trim())
getResult(num)
})
//递推公式:f(n,m)=(f(n-1,m)+m) % n
//n是数组长度,m是间隔数
function getResult(num){
var last = 0 //初始值,只有一个数,那么这个数的下标值为0
var m = 3
for(var i = 2;i <= num;i++){ //i从1开始,一直推到num
last = (last+m)%i //递推公式,从小往大推,last表示当数组长度为i时,剩下数的下标值
}
console.log(last) //推到最后就是数组长度为num,可以存活数的下标值
}