剑指 Offer 62. 圆圈中最后剩下的数字(数学,递归&递推,约瑟夫环)

剑指 Offer 62. 圆圈中最后剩下的数字

【数学,递归&递推,约瑟夫环】

  • 方法1:链表模拟

    • (n-1)轮,删除 O ( 1 ) O(1) O(1)
    • 复杂度 O ( m n ) O(mn) O(mn),不能接受
  • 方法2:数学,递归&递推

    • 约瑟夫环问题:n个人排成一个圆圈做游戏,每轮游戏去掉第m个人,然后从第(m+1)个开始计数开始新一轮,直到剩余一个人。

    • 分析:

      • 共n个数,每轮去掉一个数,显然需要有(n-1)轮,直到最后剩余1个数为止

        • 每轮去掉的都是第m个数,会把第(m+1)个数移到第一位

          • 所以对于有i个数的数组,它去掉第m个数,把第(m+1)个数移到第一位后,变成了有(i-1)个数的数组

            • 这两个数组(即两个状态)间有什么联系?
              • 因为有i个数的数组,把第(m+1)个数移到了第一位,对于第m个数,如果没被去掉,应该在有(i-1)个数的数组的最后一位
                • 设有i个数的数组的状态为(i),有(i-1)个数的数组的状态为(i-1)
              • 所以状态(i-1)是把状态(i)的元素循环左移了m位!
              • 所以对状态(i)来说,它里面元素对应的编号,应该是状态(i-1)元素的对应编号循环右移m位得到的
                • 即f(i) = (f(i-1) + m) % n
                • 但其它元素在游戏过程都被去掉了,只有最终剩余的那个数一直存在最后一轮(即状态:数组中只有1个数),所以这个递归式只适用于最终剩余的那个元素
                  • 正好是题目要求求的
                  • f[i]是最终剩余的那个元素的编号
                • 递归边界:当数组中只有1个数时,游戏结束,f[1]显然为0
                  • 写成递归那就从f[1]=0开始正向推,直到f[n]
                • 该题元素与编号是一一对应关系,所以求编号就是求元素
          • 举例(为清晰,把数组中的元素写成字母)

            • 设n=8,m=3

            • 0	 1	  2	  3	  4	  5	  6	  7
              A	 B    (C)  D   E   F  [G]  H   // n=8, id = (3+3)%8=6
              D	 E    (F) [G]  H   A   B //n=7, id = (0+3)%7 = 3
              [G]	 H    (A)  B   D   E //n=6, id = (3+3)%6 = 0
              B	 D    (E) [G]  H //n=5, id = (0+3)%5 = 3
              [G]	 H    (B)  D	//n=4, id = (1+3)%4 = 0
              D	[G]   (H)	//n=3, id = (1+3) % 3 = 1
              (D)	[G]  //n=2,id = (0+3) % 2 = 1
              [G] //n=1,id = 0
              

递归:

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

递推:

    int lastRemaining(int n, int m){
        int pos = 0;
        for(int i = 2; i <= n; i++){
            pos = (pos+m) % i;
        }
        return pos;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值