首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【详解】使用Java解决约瑟夫环问题

【详解】使用Java解决约瑟夫环问题

原创
作者头像
大盘鸡拌面
发布2026-03-20 10:27:47
发布2026-03-20 10:27:47
1100
举报

使用Java解决约瑟夫环问题

简介

约瑟夫环问题是一个经典的数学问题,描述了n个人围成一圈,从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。这个问题可以通过多种方法解决,本文将介绍一种基于数学公式的高效解法,并提供相应的Java实现。

数学公式解法

约瑟夫环问题可以通过递推公式来求解,其递推公式如下:

\[ f(n, m) = \begin{cases} 0 & \text{if } n = 1 \\ (f(n-1, m) + m) \mod n & \text{if } n > 1 \end{cases} \]

其中:

  • \( f(n, m) \) 表示n个人报数m时最后留下的人的位置。
  • 初始条件是 \( f(1, m) = 0 \),表示只有一个人时,最后留下的人是第0号(从0开始计数)。

通过这个递推公式,我们可以逐步计算出最后留下的人的位置。

Java实现

下面是使用Java实现上述递推公式的代码:

代码语言:javascript
复制
public class JosephusProblem {
    /**
     * 计算约瑟夫环问题中最后留下的人的位置
     *
     * @param n 人数
     * @param m 报数的数字
     * @return 最后留下的人的位置(从0开始计数)
     */
    public static int findLastPerson(int n, int m) {
        if (n == 1) {
            return 0;
        }
        return (findLastPerson(n - 1, m) + m) % n;
    }

    public static void main(String[] args) {
        int n = 10; // 人数
        int m = 3;  // 报数的数字
        int lastPerson = findLastPerson(n, m);
        System.out.println("最后留下的人是原来的第 " + (lastPerson + 1) + " 号");
    }
}
代码解释
  1. findLastPerson 方法:
  • 参数 ​​n​​ 表示总人数。
  • 参数 ​​m​​ 表示报数的数字。
  • 如果 ​​n​​ 等于1,返回0,因为只有一个人时,最后留下的人是第0号。
  • 否则,递归调用 ​​findLastPerson(n - 1, m)​​ 并计算 ​​(f(n-1, m) + m) % n​​。
  1. main 方法:
  • 定义人数 ​​n​​ 和报数的数字 ​​m​​。
  • 调用 ​​findLastPerson​​ 方法计算最后留下的人的位置。
  • 输出结果,注意位置是从0开始计数的,所以输出时加1。

时间复杂度

该算法的时间复杂度为 \( O(n) \),因为每次递归调用都会减少一个元素,直到 ​​n​​ 减少到1为止。空间复杂度为 \( O(n) \),因为递归调用会占用栈空间。

约瑟夫环问题是一个经典的算法问题,可以通过多种方式解决,包括递归、迭代和数学公式。下面我将提供一个使用Java实现的解决方案,该方案基于数学公式,时间复杂度为O(1)。

数学公式解法

对于约瑟夫环问题,可以使用以下递推公式来解决:

\[ f(n, m) = (f(n-1, m) + m) \mod n \]

其中:

  • \( n \) 是人数。
  • \( m \) 是报数的步长(在这个问题中,m=3)。
  • \( f(n, m) \) 表示最后留下的人的编号(从0开始计数)。

最终结果需要转换为从1开始计数的编号。

Java 实现
代码语言:javascript
复制
public class JosephusProblem {

    // 计算最后留下的人的编号(从1开始计数)
    public static int findLastPerson(int n, int m) {
        // 初始化,当只有一个人时,最后留下的人是0号
        int lastPerson = 0;

        // 从2人开始,逐步增加到n人
        for (int i = 2; i <= n; i++) {
            // 根据递推公式计算
            lastPerson = (lastPerson + m) % i;
        }

        // 转换为从1开始计数的编号
        return lastPerson + 1;
    }

    public static void main(String[] args) {
        int n = 10; // 人数
        int m = 3;  // 报数的步长

        int result = findLastPerson(n, m);
        System.out.println("最后留下的人是原来的第 " + result + " 号");
    }
}
解释
  1. 初始化:当只有一个人时,最后留下的人是0号(从0开始计数)。
  2. 递推计算:从2人开始,逐步增加到n人,每次根据递推公式计算当前人数下的最后留下的人的编号。
  3. 结果转换:最后的结果是从0开始计数的编号,需要加1转换为从1开始计数的编号。
示例运行

假设 ​​n = 10​​,​​m = 3​​,运行上述代码会输出:

代码语言:javascript
复制
最后留下的人是原来的第 4 号

这意味着在10个人围成一圈,从1到3报数的情况下,最后留下的人是原来的第4号。约瑟夫环问题是一个经典的递归问题,可以通过多种方式解决,包括直接模拟、递归和数学公式。这里我们使用Java语言来实现一个高效的解决方案,采用数学公式的方法,因为这种方法的时间复杂度为O(n),非常高效。

约瑟夫环问题的数学解法

对于约瑟夫环问题,有一个著名的数学公式可以用来快速求解:

\[ f(n, m) = (f(n-1, m) + m) \% n \]

其中:

  • \( n \) 是人数。
  • \( m \) 是每次报数的数字(在这个问题中是3)。
  • \( f(n, m) \) 表示从 \( n \) 个人中,每次报数到 \( m \) 的人出圈,最后剩下的人的位置(从0开始编号)。

初始条件是 \( f(1, m) = 0 \),即只有1个人时,最后剩下的人就是这个人自己,位置为0。

Java代码实现
代码语言:javascript
复制
public class JosephusProblem {

    public static int findLastPerson(int n, int m) {
        // 初始条件:只有1个人时,最后剩下的人的位置是0
        int pos = 0;

        // 动态计算每个人出圈后,最后剩下的人的位置
        for (int i = 2; i <= n; i++) {
            pos = (pos + m) % i;
        }

        // 返回最后剩下的人的位置(从1开始编号)
        return pos + 1;
    }

    public static void main(String[] args) {
        int n = 5; // 人数
        int m = 3; // 报数的数字

        int lastPerson = findLastPerson(n, m);
        System.out.println("最后留下的是原来第 " + lastPerson + " 号的那位。");
    }
}
代码解释
  1. findLastPerson 方法:
  • 参数 ​​n​​ 表示人数。
  • 参数 ​​m​​ 表示每次报数的数字。
  • 初始化 ​​pos​​ 为0,表示只有1个人时,最后剩下的人的位置是0。
  • 使用一个循环从2到n,逐步计算每轮出圈后,最后剩下的人的位置。
  • 最后返回 ​​pos + 1​​,因为题目要求从1开始编号。
  1. main 方法:
  • 定义人数 ​​n​​ 和报数的数字 ​​m​​。
  • 调用 ​​findLastPerson​​ 方法计算最后剩下的人的位置。
  • 打印结果。
示例

假设 ​​n = 5​​,​​m = 3​​,则输出应该是:

代码语言:javascript
复制
最后留下的是原来第 4 号的那位。

这个方法的时间复杂度为O(n),非常高效,适用于较大的输入规模。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用Java解决约瑟夫环问题
    • 简介
    • 数学公式解法
    • Java实现
      • 代码解释
    • 时间复杂度
      • 数学公式解法
      • Java 实现
      • 解释
      • 示例运行
      • 约瑟夫环问题的数学解法
      • Java代码实现
      • 代码解释
      • 示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档