Josephus 约瑟夫环问题图解
经典案例#
-
古代某法官要判决 n 个犯人死刑,他有一条荒唐的逻辑,将犯人首尾的相接排成圆圈,然后从第 start 开始数起,每数到第 distance 个犯人,就拉出来处决;然后又数 distance 个,数到的犯人又拉出来处决,依次类推。剩下的最后一人可以豁免。
-
一群猴子排成一圈,按1,2,…,n依次编号。然后从第 start 只开始数,数到第 distance 只,把它踢出圈,从它后面再开始数,再数到第 distance 只,在把它踢出去…,如此不停的进行下去,直到最后只剩下一只猴子为止,那只猴子就叫做大王。
题意说明#
采用线性表标记 n 个人,设 n = 5, start = 1, distance = 3, 5 个人分别标记为 A B C D E,
josephus(5,1,3)
环问题的求解过程如图:
算法描述#
求解 Josephus 环问题, n个人,从 start 开始计数,每次数到 distance 的人出环
Java 实现#
/**
* @param n n 个人
* @param start 从 start 开始计数
* @param distance 每次数到 distance的人出环
* @return int 最后的结果
*/
public static int josephus(int n, int start, int distance) {
if (n <= 0 || start < 0 || start >= n || distance <= 0 || distance >= n) {
throw new IllegalArgumentException("参数异常");
}
// 创建一个线性表对象 List 集合并插入从 1 开始的 n 个元素
ArrayList<Integer> arr = new ArrayList<>();
for (int i = 1; i <= n; i++) {
arr.add(i);
}
while (n > 1) {
// start 循环计数到 distance, 第 start 个元素出环即删除,其后若干元素向前移动一位
int len = arr.size();
// 计算出下一次出环的人 (当前计数 + 每次数的数量 - 1) % 当前人数 O(n)
// start 本指向上一次出环的元素,但出环后元素全部向前移动一位,start 也将指向下一为元素,所以需要减一
start = (start + distance - 1) % n;
arr.remove(start);
n--;
}
return arr.get(0);
}
分类:
Algorithm
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)