最近一段时间一直在找工作,没有心思写心得。今天刚好从淳中视讯面试回来,有一道题很有意思。
1. n个人围成一个圆圈,从1到3开始报数,报到3的人出去,这样一直循环,直到只剩下一个人。问剩下的人在开始报数之前的编号?
当时我想的是直接用循环链表来模拟整个报数的过程,即构造一个n个数的循环链表,进行循环遍历,每当数到3时删除当前指向的节点,直到剩下最后一个。
但是该算法比较复杂,肯定还有简单的算法。
回来查了一下百度果然是这样,这是经典的约瑟夫问题:
据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
我们回到解题思路上,考虑一般的情况,n个人排成一圈,从第1个人开始报数,报数口号从1到m(报到m的人从圆圈里出去),循环直到只剩一个人,问最后剩下的人开始的编号是多少?
假设答案ans = F(n,m)。则F(1,m)=1; F(2,2) = 1; F(2,3) = 2;
假设有n个数: 1,2,3,4,5,6....,n-2,n-1,n。
中奖的第一个人的序号一定是:a1 = (m%n ).那么剩下的人构成一个n-1约瑟夫环:
1,2,3...a1-1,a1+1...n-1,n.
即: a1+1,a1+2....1,2,...a1-1. 每个元素做映射:
a1+1 -> 1,
a1+2 -> 2,
.....
a1-1 -> n-1.
剩下的数构成一个新的约瑟夫环并且规模为n-1.
因为从n转换到