Solution 18: 约瑟夫环问题

问题描述

n个数字(0,1,...,n-1)形成一个圆圈,从数字0开始。每次从这个圆圈中删除第m个数字,然后从被删除的下一个继续删除第m个元素,以此类推。

直到最后剩下一个数字,求出该数字。

解决思路

1. 使用循环链表模拟这一过程,计数器计数;

2. 递归思路

(图片来源:http://www.cnblogs.com/yangyh/archive/2011/10/30/2229517.html)

程序

public class JosephLoop {
	public int josephLoopByList(int n, int m) {
		if (n <= 0 || m <= 0) {
			return -1;
		}

		int cnt = n;
		boolean[] p = new boolean[n];
		int k = 0;

		while (cnt > 1) {
			for (int i = 0; i < p.length; i++) {
				if (!p[i]) {
					++k;
					if (k == m) {
						p[i] = true;
						--cnt;
						k = 0;
					}
				}
			}
		}

		for (int i = 0; i < p.length; i++) {
			// get the last one
			if (!p[i]) {
				return i + 1;
			}
		}

		return -1;
	}

	// recursion
	public int josephLoopRec(int n, int m) {
		if (n <= 0 || m <= 0) {
			return -1;
		}
		return helper(n, m, n) + 1;
	}

	private int helper(int n, int m, int i) {
		if (i == 1) {
			return (m - 1) % n;
		}
		return (helper(n - 1, m, i - 1) + m) % n;
	}
}

  

时间: 2024-11-01 04:20:15

Solution 18: 约瑟夫环问题的相关文章

ytu 1067: 顺序排号(约瑟夫环)

1067: 顺序排号Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 31  Solved: 16[Submit][Status][Web Board] Description 有n人围成一圈,顺序排号.从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位. Input 初始人数n Output 最后一人的初始编号 Sample Input 3 Sample Output 2 HINT Source freepro

循环单向链表(约瑟夫环)

#include <stdio.h> #include <stdlib.h> typedef struct List { int data; struct List *next; }List; //创建循环单向链表n为长度 List *list_create(int n) { List *head, *p; int i; head = (List *)malloc(sizeof(List)); p = head; p->data = 1; //创建第一个结点 for (i =

cdoj525-猴子选大王 (约瑟夫环)

http://acm.uestc.edu.cn/#/problem/show/525 猴子选大王 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 有m个猴子围成一圈,按顺时针编号,分别为1到m.现打算从中选出一个大王.经过协商,决定选大王的规则如下:从第一个开始顺时针报数,报到n的猴子出圈,紧接着从下一个又从1顺时针循环报数,...,如此下去,最后剩

poj 2886 Who Gets the Most Candies?(线段树+约瑟夫环+反素数)

Who Gets the Most Candies? Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 9934   Accepted: 3050 Case Time Limit: 2000MS Description N children are sitting in a circle to play a game. The children are numbered from 1 to N in clockwise o

用循环链表解决约瑟夫环问题

约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列:依此规律重复下去,直到圆桌周围的人全部出列. 下面我们用循环列表模拟这个过程: 1 //节点定义与单链表相同,在此省略 2 //use cyclical linked list to solve josephus problem 3 template <typename Type> class Linked

约瑟夫环----循环链表问题

我们构造一个循环链表来表示排成圆圈的人.每个人的链接指向圆圈内在他左边的人.正数i表示圆圈内的第i个人.已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列:依此规律重复下去,直到圆桌周围的人全部出列.通常解决这类问题时我们把编号从0~n-1,最后结果+1即为原问题的解. 一道算法面试题如下: 约瑟夫环问题:一圈共有N个人,开始报数,报到M的人自杀,然后重新开始报数,问最后自杀的人是谁? 如

C语言数组实现约瑟夫环问题,以及对其进行时间复杂度分析

尝试表达 本人试着去表达约瑟夫环问题:一群人围成一个圈,作这样的一个游戏,选定一个人作起点以及数数的方向,这个人先数1,到下一个人数2,直到数到游戏规则约定那个数的人,比如是3,数到3的那个人就离开这个游戏:按这样的规则,剩下一个人,游戏就结束,这个人就为赢家.(读者可以试着表达,不认同,直接忽略) 抽象分析 这个人就是一个数据个体,数据结点,数据元素.上面产生的数据结构为:单方向循环的链.可以用链表实现,也可以用数组来实现. 链表到数组的迁移 人(数据元素. 数据结点.数据个体) 结点关系 (

1139 约瑟夫环问题

1139 约瑟夫环问题 时间限制:500MS  内存限制:65536K提交次数:157 通过次数:79 题型: 编程题   语言: G++;GCC Description 约瑟夫(josephus)环是这样的:假设有n个小孩围坐成一个圆圈,并从1开始依次给每个小孩编上号码.老师指定从第s位小孩起从1开始报数,当数到m时,对应的小孩出列,依次重复,问最后留下的小孩是第几个小孩?例如:总共有6个小孩,围成一圈,从第一个小孩开始,每次数2个小孩,则游戏情况如下: 小孩序号:1,2,3,4,5,6 离开

约瑟夫环问题-Java数组解决

约瑟夫环问题说的是,n个人围成一圈,从第k个人开始沿着一个方向报数,报到第m个人时,第m个人出列,从紧挨着的下一个人(未出列)开始,求整个环中人的出列顺序.下面是我用java实现的解决方法. 1 class JosephLoop 2 { //n为环中人数,m为每次报数的人数,k为报数的起始位置0-n 3 int n,m,k; 4 int[] persons; 5 int[] seq; 6 7 JosephLoop(int n, int k, int m){ 8 this.n = n; 9 thi