剑指offer 圆圈中最后剩下的数字(约瑟夫环,dfs)

题目链接

题目描述
0 , 1 , … , n − 1 0,1,\dots ,n-1 0,1,,n1 n n n 个数字排成一个圆圈,从数字 0 0 0 开始,每次从这个圆圈里删除第 m m m 个数字(删除后从下一个数字开始计数)。求出这个圆圈里剩下的最后一个数字。
例如, 0 、 1 、 2 、 3 、 4 0、1、2、3、4 01234 5 5 5 个数字组成一个圆圈,从数字 0 0 0 开始每次删除第 3 3 3 个数字,则删除的前 4 4 4 个数字依次是 2 、 0 、 4 、 1 2、0、4、1 2041,因此最后剩下的数字是 3 3 3

输入: n = 5, m = 3
输出: 3
输入: n = 10, m = 17
输出: 2

限制: 1 ≤ n ≤ 1 0 5 1 \le n \le 10^5 1n105 1 ≤ m ≤ 1 0 6 1 \le m \le 10^6 1m106

思路

参考了:leecode官方题解

  • 递归思路,假设 f ( n , m ) f(n,m) f(n,m) 返回的是, n n n 个人,每 m m m 个淘汰一人,最后剩下的人的编号
  • 第一次消除的是编号为 y = ( m − 1 ) % n y=(m-1)\%n y=(m1)%n 的人
  • x = f ( n − 1 , m ) x=f(n-1,m) x=f(n1,m),那么 f ( n , m ) = ( y + x + 1 ) % n = ( m + x ) % n f(n,m)=(y+x+1)\%n=(m+x)\%n f(n,m)=(y+x+1)%n=(m+x)%n
  • f ( 1 , m ) = 0 f(1,m)=0 f(1,m)=0

这里的 f ( n , m ) = ( m + x ) % n f(n,m)=(m+x)\%n f(n,m)=(m+x)%n 相当于一个加了一个偏移量。比如 f ( 10 , 17 ) f(10,17) f(10,17),第一个淘汰的人的编号为 6 6 6,那么 f ( 9 , 17 ) f(9,17) f(9,17) 就不是从编号为 0 0 0 的人开始数,而是从编号为 7 7 7 的人开始数。同样,最后剩下的人的编号也不是 x = f ( 9 , 17 ) x=f(9,17) x=f(9,17),它同样要加上一个偏移量: f ( 10 , 17 ) = ( 6 + 1 + f ( 9 , 17 ) ) % 10 f(10,17)=(6+1+f(9,17))\%10 f(10,17)=(6+1+f(9,17))%10

代码

int lastRemaining(int n, int m) {
    if(n==1) return 0;
    int x=lastRemaining(n-1,m);
    return (m+x)%n;
}

时间 O ( n ) O(n) O(n),空间 O ( n ) O(n) O(n)。要求空间 O ( 1 ) O(1) O(1),递归改迭代:

int lastRemaining(int n,int m){
    int res=0;
    for(int i=2;i<=n;i++) res=(res+m)%i;
    return res;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

m0_51864047

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值