圆圈中最后剩下的数字(约瑟夫问题)

0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
示例 1:输入: n = 5, m = 3 输出: 3
示例 2:输入: n = 10, m = 17 输出: 2

计算公式: f(n, m) = (f(n-1, m) + m) % n
其中n表示一共有多少个数字,m表示数到第几个

递归

从数字0开始,每次从这个圆圈里删除第m个数字: 表示编号从0开始算起

public static void main(String[] args) {
      System.out.println(lastRemaining(5, 3));
    }
    // 计算公式: f(n, m) = (f(n-1, m) + m) % n
    // 递归
    public static int lastRemaining(int n, int m) {
            if (n == 1)  return 0;
          return  (lastRemaining(n-1,m) + m) % n;
    }

非递归

 //
    /*
    * f(5, 3) = (f(4, 3) + 3) % 5
    * f(4, 3) = (f(3, 3) + 3) % 4
    * f(3, 3) = (f(2, 3) + 3) % 3
    * ...
    * f(2, 3) = (f(1, 3) + 3) % 2
    * f(1, 3) = 0
    *
    *
    * */
    // 非递归
    public static int lastRemainingF(int n, int m) {
        int res = 0;
        int begin = 2;
        while (begin <= n) {
           res =  (res + m) % begin;
            begin++;
        }

//        for (int i = 2; i <= n; i++) {
//            res =  (res + m) % i;
//        }
        return res;

    }

推导公式

如果改为从数字1开始,每次从这个圆圈里删除第m个数字: 表示编号从1开始算起,结果都是先计算编号从0开始的结果加上差值1就好

递归

public static void main(String[] args) {
      System.out.println(lastRemaining(5, 3) );
    }
    // 计算公式: f(n, m) = (f(n-1, m) + m) % n
    public static int lastRemaining(int n, int m) {
           return f(n, m) + 1;// 编号从0开始算出的结果加上偏值1
    }
    public static f(int n, int m) {
     if (n == 1)  return 0;
          return  (lastRemaining(n-1,m) + m) % n;
    }

非递归

 public static int lastRemainingF(int n, int m) {
        int res = 0;
        int begin = 2;
      for (int i = 2; i <= n; i++) {
          res =  (res + m) % i;
       }
        return res + 1; // 编号从0开始算出的结果加上偏值1
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值