剑指offer62 圆圈中最后剩下的数字
最基本的方法当然是利用链表,然后按照顺序一个个删除,留下最后的就是结果。时间复杂度O(mn)。
那么有没有什么更简单的方法呢?
我们发现,如果将n个数字每次删除第m个最后留下的数字定义为f(n,m)。
那么假设第一次删除的数是k(=(m-1)%n),对于剩下的数k+1,k+2,...,n-1,0,k-1,将之重新排为0~n-2后,剩余的数字为f2(n-1,m)。
那么f(n,m)==f2(n-1,m)。
f2分为两步操作,一是重排剩下的序列,即,搞一个新的映射出来,直接在原数组上得到最终结果,二是递归。
而映射过程也很简单,就是
开始是 0~n-1 对应 0~n-1
第二轮 k+1,k+2,...,n-1,0,k-1 , k 对应0~n-1
只不过k被删掉了,不会用到这个映射。
对应的映射应为 (x-k-1)%n ,逆映射 (x+k+1)%n。
则
f(1,m)=0
f(n,m)=(f(n-1,m)+m)%n
所以结果:
public class Solution { public int LastRemaining_Solution(int n, int m) { if(n<1||m<1) return -1; int ans = 0; for(int i=2;i<=n;i++){ ans = (ans+m)%i; } return ans; } }
运行时间:17ms
占用内存:9224k

浙公网安备 33010602011771号