题目概述
解题思路
如果采用环形链表实现,这题的时间和空间复杂度均为O(n),比较麻烦。
这里采用一个取巧的方法,通过递推公式推出最后一个被删除的元素的序号。
这道题的一个复杂之处在于,每次删除了当前数环中的一个元素以后,剩下元素的序号和它的值是不对应的。要想知道最后留下了哪个元素,就需要根据它在数环的相对序号来倒推原始的位置。
我们已知删至只剩一个元素时,该元素的序号为1;假设当数环长度为i时,待删元素的序号为Num(i),Num(1) = 1。我们现在需要明确的就是Num(i)和Num(i-1)的关系。
首先考虑一下,当数环中有i个元素时,报数A的节点编号为B,A与B的关系:B = (A - 1)%i + 1
接下来考虑从长为i的环变为长为i - 1的环时,环中元素的编号变化。假设长为i的环中,被删除元素的编号为d,其余元素在删除元素之前的编号为old,在删除元素以后的编号为new,则new 与 old的关系是:old = (new + s - 1) % i + 1。
由于每次删除的元素报数为m,即A = m, 故B = (m - 1)%i+1,也即 s = (m-1)%i+1;带入后一个等式可知, old = (new + (m-1)%i + 1 - 1)%i+1 = (new + m - 1) % i + 1。
考虑最后剩下的那个节点,它的序号递推公式为:Num(i) = (Num(i - 1) + m - 1) % i + 1,Num(1) = 1。考虑将该公式递推N次,可得原始数组中该元素的序号。
算法性能
代码样例
class Solution {
public:
/**
*
* @param n int整型
* @param m int整型
* @return int整型
*/
int ysf(int n, int m) {
// write code here
int PC = 1;
for (int i = 1; i <= n; ++i)
PC = (PC + m - 1) % i + 1;
return PC;
}
};
一些思考
考虑这道题的一个变种:如何按序输出被删除的第k个元素(k = 1,...n)?
其实第k个元素的特性是:Num(N - k) = 0。我们只需将这个其实式带入递推公式求解即可。