约瑟夫问题,看了这篇你绝对能理解!

public class JosephusProblem {

    public static int josephus(int n, int m) {

        if (n == 1) {

            return 1;

        } else {

            // 计算上一轮问题的解(规模减1)

            int prev = josephus(n - 1, m);

            // 计算当前轮问题的解

            return (prev + m - 1) % n + 1;

        }

    }

    public static void main(String[] args) {

        int n = 7; // 总人数

        int m = 3; // 报数到m的人被杀掉

        int survivor = josephus(n, m);

        System.out.println("最后剩下的人的编号是: " + survivor);

    }

}

问题的规模从1-n,每层递归返回上一轮最后一个编号prev,一直返回到n层就可以得到答案.

`(prev + m - 1) % n + 1` 是用来计算约瑟夫问题中的当前问题的解的一部分。让我解释一下这个表达式的含义:

- `prev`:这是递归调用 `(n - 1, m)` 后返回的结果,表示在问题规模减小一个人时的解,即上一轮的最后剩下的人的编号。

- `m`:表示每次报数要数的数字。

- `n`:表示当前问题中的总人数。

现在让我们逐步解释这个表达式:

1. `(prev + m - 1) % n`:首先,我们将上一轮的最后剩下的人的编号 `prev` 加上 `m - 1`,prev上一个淘汰的人开始数m,因为是淘汰的人不用数,所以-1。然后,我们对结果取模 `n`,这是因为人数是固定的,所以我们需要确保结果在 1 到 `n` 的范围内。

2. 最后,我们再加上1,以将结果从0到`n-1`的范围映射到1到`n`的范围内,得到的值就是当前问题中最后剩下的人的编号。

这个表达式的目的是计算当前问题的解,即在当前问题规模下最后剩下的人的编号。递归的基本情况是只剩下一个人时,此时 `prev` 为1,`m` 无关紧要,所以最后剩下的人的编号就是1。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值