约瑟夫环

约瑟夫环

拥有回忆 提交于 2020-02-26 15:57:05
题目: 古代某法官要判决n个犯人死刑,他有一条荒唐的逻辑,将犯人首尾的相接排成圆圈,然后从第s个人开始数起,每数到第m个犯人,就拉出来处决;然后又数m个,数到的犯人又拉出来处决,依次类推。剩下的最后一人可以豁免。 自己智商能理解的写法 public class Josephus { public static void main(String[] args) { //编号从 0 到 n-1 //最终输出 最后一个活下来的人的编号 int n = 5; // 总人数 int s = 0; // 起始的人的编号 int d = 3; // 每数到第几个人 int alive_person = n; int[] person_state = new int[n]; int current_person_index = s; int counter = 0; while( true ) { // count counter++; // judge current person if ( counter==d ) { person_state[current_person_index] = 1; // kill this person System.out.println("the person whose index is " + current_person_index+" die");

约瑟夫环问题(华科软院上机题目)

北城余情 提交于 2020-02-20 01:56:47
问题分析: 一群人(排列序号从1到N,N可设定)围成一圈,按一定规则出列,剩余的人仍然围成一圈.出列规则是顺着1到N的方向对圈内的人从1到C计数(C可设定),圈内计数为C的人出列,剩余的人重新计数,按上述规则,让圈内所有的人出列.请编程顺序输出出列编号的序列 代码如下: #include<stdio.h> int a[100]={0}; //定义一个数组,用来记录N个人的编号 //output()为输出出列编号序列的函数,参数分别为总人数N和规定出列的数字C void output(int N,int C) { int i,j,len,count=1; //count表示当前出列的数字,取值范围是1-C,故将其初始值置为1 for(i=0;i<N;i++) { a[i]=i+1; //将N个人从1到N进行编号,下标从0开始,而编号从一开始,所以下标为i的人其编号为i+1 } len=N; //len表示当前人数 for(i=0;len!=0;) //从第一个人开始进行循环,len不等于0,说明此时还有人,循环继续 { if(count==C) //如果count等于规定出列的数字 { printf("%d ",a[i]); //将这一轮编号为C的人出列,输出其在N个人中的编号 //因为count是从1开始自增,这个for循环的作用是从本轮输出的这个人开始

单向环形链表 约瑟夫问题

孤者浪人 提交于 2020-02-19 09:08:56
Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。 链表如下图 数2下 自己也要数 所以只会移动1次 构建链表,遍历链表 分析图 first.next = 2 3.next = first 让最后一个元素的next指向first 首先 创建一个环形链表 // 创建一个first节点,当前没有编号 private Boy first = null; // 添加小孩节点,构建成一个环形的链表 public void addBoy(int nums) { // nums 做一个数据校验 if (nums < 1) { System.out.println("nums的值不正确"); return; } Boy curBoy = null; // 辅助指针,帮助构建环形链表 // 使用for来创建我们的环形链表 for (int i = 1; i <= nums; i++) { // 根据编号,创建小孩节点 Boy boy = new Boy(i); // 如果是第一个小孩 第一次 if (i == 1) { first = boy; //这是头指针 把第一个的赋值给first //不太理解

#2019120700020 约瑟夫问题七问

为君一笑 提交于 2020-01-27 06:01:18
1.基本约瑟夫问题 题目描述 \(n\) 个人( \(n\le 100\) )围成一圈,从第一个人开始报数,数到 \(m\) 的人出列,再由下一个人重新从 \(1\) 开始报数,数到 \(m\) 的人再出圈,……依次类推,直到所有的人都出圈,请输出依次出圈人的编号. 输入格式 \(n m\) 输出格式 出圈的编号 样例输入 10 3 样例输出 3 6 9 2 7 1 8 5 10 4 说明 \(m, n \le 100\) 2 题意描述 已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。 输入 \(n,k,m\) 输出 按顺序输出出圈人的编号 样例输入 9 1 5 样例输出 5 1 7 4 3 6 9 2 8 3 约瑟夫问题是个有名的问题: \(N\) 个人围成一圈,从第一个开始报数,第 \(M\) 个将被杀掉,最后剩下一个,其余人都将被杀掉。例如 \(N=6\) , \(M=5\) ,被杀掉的人的序号为5,4,6,2,3。最后剩下1号。 假定在圈子里前 \(K\) 个为好人,后 \(K\) 个为坏人,你的任务是确定这样的最小 \(M\) ,使得所有的坏人在第一个好人之前被杀掉。 4 \(n\) 个人排成一圈。从某个人开始

约瑟夫环

柔情痞子 提交于 2020-01-22 19:30:56
学习体会 方法一(循环链表):无头节点的链表。寻找提出的人函数:1,定义参数sign,每进一次新链表,自加。2判断sign是否等于3。若等于,将该节点删去,并sign重置零。 来源: CSDN 作者: KJ GL 链接: https://blog.csdn.net/qq_45914759/article/details/104070454

约瑟夫环问题(递推)

牧云@^-^@ 提交于 2020-01-21 17:12:56
描述 约瑟夫问题:有n只猴子,按顺时针方向围成一圈选大王(编号从1到n),从第1号开始报数,一直数到m,数到m的猴子退出圈外,剩下的猴子再接着从1开始报数。就这样,直到圈内只剩下一只猴子时,这个猴子就是猴王,编程求输入n,m后,输出最后猴王的编号。 输入 每行是用空格分开的两个整数,第一个是 n, 第二个是 m ( 0 < m,n <=300)。最后一行是: 0 0 输出 对于每行输入数据(最后一行除外),输出数据也是一行,即最后猴王的编号 样例输入 6 2 12 4 8 3 0 0 样例输出 5 1 7 问题分析: 看到这个问题一打眼肯定是选择模拟整个过程来解题,但细心分析可以发现,这既然是一个数学问题,创立之初肯定不会是用计算机模拟的,肯定是有数学公式可以遵循的。所以我们可以从递推的角度来思考这个问题。 设n个人围城一圈报到m出列,最后的胜利者的编号设为f(n,m)。 首先我们先来看一个表格: n m f(n,m) 1 2 1 2 2 1 3 2 3 4 2 1 5 2 3 6 2 5 这个表格呢,可以这么理解 n=6,m=2.最后胜利者为五号。 那我们来尝试推一下n=5,m=2时胜利者编号。当n=5时相当于n=6问题执行完一轮之后的子问题。n=6执行完一轮之后出局者是二号,那么就从三号开始报数,这时问题就变成了,五个人围成一圈报数,数到2的人退出,编号1为1、3、4、5

单向环形链表及约瑟夫问题的java实现

时光毁灭记忆、已成空白 提交于 2020-01-21 03:18:59
约瑟夫问题(Josephu问题)也称为“丢手帕问题”。 问题描述: 设编号为1、2、3、4......的n个小朋友围成一圈,约定编号为 k 的小朋友从 1 开始报数,轮流数到 m 的小朋友出列。接着出列小朋友的下一位又从1开始报数,轮流数到 m 的小朋友出列,以此类推,直到所有小朋友都出列为止,由此产生一个出列编号的序列。 n = 5 表示有 5 个小朋友 ; k = 1 表示从第 1 个小朋友开始报数 ; m = 2 表示每次数 2 下。 本问题由于需要不断地删除节点,同时循环报数,因而用到单向环形链表。 首先创建一个节点类Boy : class Boy{ private int no ; //小孩的编号 private Boy next ; //指向下一个节点,默认为null public Boy(int no){ this.no = no ; } public int getNo() { return no; } public void setNo(int no) { this.no = no; } public Boy getNext() { return next; } public void setNext(Boy next) { this.next = next; } /* * 之所以要设置这几个构造方法,是因为Boy的几个基本属性都是private类型 */ }

环形链表与约瑟夫环问题

一曲冷凌霜 提交于 2020-01-19 16:09:47
思路: 代码: public class Josepfu { public static void main(String[] args) { // 测试一把看看构建环形链表,和遍历是否ok CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList(); circleSingleLinkedList.addBoy(125);// 加入5个小孩节点 circleSingleLinkedList.showBoy(); //测试一把小孩出圈是否正确 circleSingleLinkedList.countBoy(10, 20, 125); // 2->4->1->5->3 //String str = "7*2*2-5+1-5+3-3"; } } // 创建一个环形的单向链表 class CircleSingleLinkedList { // 创建一个first节点,当前没有编号 private Boy first = null; // 添加小孩节点,构建成一个环形的链表 public void addBoy(int nums) { // nums 做一个数据校验 if (nums < 1) { System.out.println("nums的值不正确"); return; } Boy

通过例子进阶学习C++(六)你真的能写出约瑟夫环么

旧街凉风 提交于 2020-01-17 10:07:20
本文是通过例子学习C++的第六篇,通过这个例子可以快速入门c++相关的语法。 1.问题描述 n 个人围坐在一个圆桌周围,现在从第 s 个人开始报数,数到第 m 个人,让他出局;然后从出局的下一个人重新开始报数,数到第 m 个人,再让他出局......,如此反复直到所有人全部出局为止。 2.问题分析及用数组求解 约瑟夫环是经典的算法问题,如同“一千个读者就有一千个哈姆雷特”,该问题每个人都有不同的解答。常见的有:数组;单向循环链表;静态链表;双向链表;队列;递推公式 ...... 首先简化问题,从s=1开始数,通过数组实现需要: ​ 数组 bool a[1000],可能会浪费了大量的存储空间; ​ 变量 t 从s=1开始数,指示当前数组的位置; ​ 变量 f 记录出局人数; ​ 变量 s 从1到m; 整个过程一个do-while循环即可实现,但理解起来却是非常“拗口”。 代码如下: #include<iostream> using namespace std; int n,m,s,f,t; bool a[1000]; int main() { cin>>n>>m; //共n人,从1开始数,数到m出局 for (int i=1;i<=n;++i){ a[i]=false; } t=0;//从数组a的a[1]开始...记录数组a的第t个位置 f=0;//记录出局人数 s=0;/

5. 环形链表实现约瑟夫问题

大城市里の小女人 提交于 2020-01-11 17:15:22
一、概念 1. 环形链表 环形链表是另一种形式的链式存贮结构。它的特点是表中最后一个结点的指针域指向第一个结点,整个链表形成一个环。 2. 约瑟夫问题 设编号为1,2,…,n 的n个人围坐一圈,约定编号为 k (1 ≤ k ≤ n) 的人从1开始报数,数到m的那个人出列,出列的人的下一位又从1开始报数,数到m的那个人又出列,以此类推,直到所有人都出列为止,由此产生一个出队编号的队列。 二、环形链表和约瑟夫问题的实现 1. 环形链表的实现 思路: 先定义一个 first 变量初始值为空,目的是让 first 指向环形链表的第一个结点; 为保证first变量不能移动,所以应该定义一个辅助变量 curr 来帮助后续的结点加入构成环形链表,curr的初始值也为null; 在加入第一个结点时,就让 first 指向该节点,first的next指向自己,curr此时处于第一个结点的位置, 即first = boy,first.next = first,curr = first,从而形成一个环; 从加入第二个节点开始,就让 curr 变量 next 指向这个加入的新结点,新结点的 next 指向第一个结点, 即curr.next = newBoy,newBoy.next = first,curr = boy; 后面当我们每创建一个新结点,就把该结点加入到已有的环形链表中即可。 代码实现: /**