问题描述:
有 n 个人围成一个圈,每 q 个人踢掉一个人,问最后留下来的人是几号?
使用链表暴力求解时间复杂度是 O(qn),递归的话是 O(n) ,使用这个方法可以加速到 O(logn).
解法思路:
假设初始编号为 1,2,3 … n ,现在考虑一种新的编号方式。
第一个人不会被踢掉,那么他的编号从 n 开始往后加 1 ,变成 n+1 ,然后第二个人编号变为 n+2 ,直到第 q 个人,他被踢掉了。
然后第 q+1 个人编号继续加 1 ,变成了 n+q ,依次下去。
考虑当前踢到的人编号为 kq,那么此时已经踢掉了 k 个人,所以接下去的人新的编号为 n+k(q-1)+1…。
所以编号为 kq+d 的人编号变成了 n+k(q-1)+d ,其中 1<=d<q;
直到最后,可以发现活下来的人编号为 qn ,问题是怎么根据这个编号推出他原来的编号?
以 n=10 , q=3 为例,下图就是每个人新的编号:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|
11 | 12 | T | 13 | 14 | T | 15 | 16 | T | 17 |
18 | T | 19 | 20 | T | 21 | 22 | |||
T | 23 | 24 | T | 25 | |||||
26 | T | 27 | |||||||
28 | T | ||||||||
29 | |||||||||
30 | |||||||||
令:
N = n + k ( q − 1 ) + d \quad N=n+k(q-1)+d N=n+k(q−1)+d
则他上一次的编号为:
k q + d = k q + N − n − k ( q − 1 ) = k + N − n \quad kq+d=kq+N-n-k(q-1)=k+N-n kq+d=kq+N−n−