题目描述:0,1,···,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字(删除后从下一个数字开始计数)。求出这个圆圈里剩下的最后一个数字。例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
链接:https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof
建设
f
(
n
)
f(n)
f(n)表示0,1,···,n-1循环删除后的解,现在我们来讨论
f
(
n
)
f(n)
f(n)的解与
f
(
n
−
1
)
f(n-1)
f(n−1)的解之间的关系。
将(1)中的第m个元素删除后,我们需要删除(2)中的第m个元素。
对序列(2)进行重新编号我们得到序列(4),并且(2)中的数据可以通过对(4)中的数据进行(3)中的映射得到。求解序列(4)得到的解是
f
(
n
−
1
)
f(n-1)
f(n−1),通过对
f
(
n
−
1
)
f(n-1)
f(n−1)进行(3)中的映射我们可以得到序列(2)的解。并且需要注意的是序列(2)的解和序列(1)的解是相同的。因此,我们可以通过求解
f
(
n
−
1
)
f(n-1)
f(n−1)再对其进行映射得到
f
(
n
−
1
)
f(n-1)
f(n−1)的解。也就是
f
(
n
)
=
(
f
(
n
−
1
)
+
m
)
%
n
f(n)=(f(n-1) + m)\%n
f(n)=(f(n−1)+m)%n。于是得到如下递归和非递归算法:
public int lastRemaining(int n, int m) {
return n == 1 ? 0 : (lastRemaining(n - 1, m) + m%n)%n;
}
public int lastRemaining(int n, int m) {
int ans = 0;
for(int i = 2; i <= n; i++){
ans = (ans + m%i)%i;
}
return ans;
}