约瑟夫环问题研究(一)

2023-05-16

最近在看C方面的东西,看到了李明老师讲解的约瑟夫环问题,感觉很有意思,于是在看了他的讲解之后,自己又重新按照他的思路进行了编写,整理如下:

问题描述:约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。通常解决这类问题时我们把编号从0~n-1,最后结果+1即为原问题的解。

代码一:

/**
 * 约瑟夫环问题的研究
 * @author ryn
 * 
 */

public class Josephu {
	
	private static int ALL = 6;		//总共进行游戏的人数
	private static int OUT = 3;		//规定的数字(每数到3就出局)
	private static int[] people = new int[ALL];	//定义游戏的人数组
	
	public static void main(String[] args) {
		init();
		print();
		execute();
	}

	/**
	 * 执行出局操作
	 */
	private static void execute() {
		int left = ALL;		//剩下游戏的人数
		int counter = 0;	//计数器
		int index = 0;		//游戏对应索引值(下标值)
		
		//当还没有人出局,就继续进行出局操作
		while(left > 0) {
			
			//如果对应当前索引的人没有出局,则让计数器加1
			if(people[index] > 0) {
				counter++;
			}
			
			if(counter == OUT) {
				//每次执行了出局操作就将剩下的人数减1
				left--;
				System.out.println("people " + people[index] + " is out!");
				//将出局了的人的对应值置为0
				people[index]  = 0;
				//重置计数器
				counter = 0;
			}
			
<span style="white-space:pre">			</span>//print();
			System.out.println("index: " + index + " counter: " + counter + " left: " + left);
			
			//索引自增,指向下一个人
			index++;
			
			//当索引越界,让其重新值为第一个人
			if(index == ALL) {
				index = 0;
			}
		}
	}

	/**
	 * 进行打印操作
	 */
	private static void print() {
		for(Integer i : people) {
			System.out.print(i + " ");
		}
		System.out.println();
	}

	/**
	 * 进行初始化操作
	 */
	private static void init() {
		for(int i = 0; i < ALL; i++) {
			people[i] = i + 1;
		}
	}
}

当我们将打印数组的函数取消注释时,打印的结果是:

我只是截取了其中的一小部分,可以看到,其中每次循环其实都进行了很多无用的比较(也就是每次都要判断数组中对应的值是不是大于0)

那么有没有什么办法能够去除这些无用的比较呢?

那就是设置一个指向下一个有效元素的数组,保存下一个有效元素的索引值,这样,每次比较的值必定是大于0的

代码如下:

/**
 * 约瑟夫环问题的研究
 * @author ryn
 * 
 */

public class Josephu {
	
	private static int ALL = 6;		//总共进行游戏的人数
	private static int OUT = 3;		//规定的数字(每数到3就出局)
	private static int[] people = new int[ALL];	//定义游戏的人数组
	private static int[] next = new int[ALL];	//定义对应的指向下一个人的数组
	
	public static void main(String[] args) {
		init();
		print();
		execute();
	}
	
	/**
	 * 执行出局操作
	 */
	private static void execute() {
		int left = ALL;		//剩下游戏的人数
		int counter = 0;	//计数器
		int index = 0;		//游戏对应索引值(下标值)
		int prev = ALL - 1;	//0号索引值对应的前一位就应该是整个索引表的最后一位
		
		//当还没有人出局,就继续进行出局操作
		while(left > 0) {
			
			//如果对应当前索引的人没有出局,则让计数器加1
			if(people[index] > 0) {
				counter++;
			}
			
			if(counter == OUT) {
				//每次执行了出局操作就将剩下的人数减1
				left--;
				System.out.println("people " + people[index] + " is out!");
				//将下一个未出局的人的索引赋值给上一个未出局人的索引
				next[prev] = next[index];
				//将出局了的人的对应值置为0
				people[index]  = 0;
				//重置计数器
				counter = 0;
			}
			
			//print();
			System.out.println("index: " + index + " counter: " + counter + " left: " + left);
			
			//记录上一个未出局人的索引值
			prev = index;
			//使index的值每次循环都具有意义(不需要比较出局了的人)
			index = next[index];
		}
	}

	/**
	 * 进行打印操作
	 */
	private static void print() {
		for(Integer i : people) {
			System.out.print(i + " ");
		}
		System.out.print("people\n");
		for(Integer i : next) {
			System.out.print(i + " ");
		} 
		System.out.print("next\n");
	}

	/**
	 * 进行初始化操作(包括游戏人和对应链表)
	 */
	private static void init() {
		for(int i = 0; i < ALL; i++) {
			people[i] = i + 1;
		}
		for(int i = 0; i < ALL; i++) {
			next[i] = (i + 1) % ALL;
		}
	}
}

这次打印的结果如下:


这次可以看到,每次的操作都只是进行了上次比较,那么效率就提高了不止一点了

那么细看一下代码,是不是还有什么优化的地方呢?


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

约瑟夫环问题研究(一) 的相关文章

随机推荐

  • Android实战开发--底部导航(Fragment)篇

    安卓实战开发之底部导航 提示 xff1a 本篇文中对基本的操作不做细节讲解 xff0c 后续会通过链接方式跳转到对应的知识点 文章目录 安卓实战开发之底部导航前言一 准备1 矢量图标准备2 文件准备 二 使用步骤1 在fragment中动态
  • android N进程启动流程(一)(捕获输入事件、准备创建activity、焦点切换)

    android N进程启动流程 一 捕获输入事件 准备创建activity 焦点切换 1 背景 本文主要针对event log中各处节点进行进程启动流程分析 span class token comment 此处使用的是adb指令input
  • 目标检测类前言知识

    1 PASCAL数据集 有关目标检测 xff0c 目标分类 xff0c 目标分割 xff0c 动作识别 1 xff09 下载的数据集文件介绍 标注信息 xff1a xml文件实例 xff1a lt segmented gt 1 被分割 0
  • 最新网狐荣耀版整理、编译和搭建教程

    一 安装visual studio 2015 xff0c 在百度就能搜索到下载地址 xff0c 在教程最后 xff0c 会给大家包括所有工具在内的集成包 因为visual studio 2015体积比较大 xff0c 而且安装过程很漫长 x
  • windows efi分区修复

    在windows下一阵瞎搞 xff0c 把efi分区的efi标识搞没了 xff0c 导致deepin无法识别efi分区 xff0c update grub2命令失败 其实windows也找不到efi标识了 xff0c 但没有影响启动 因为W
  • XML 根级别上的数据无效。 行 1,位置 1

    上午 xff1a 将XML数据保持到数据中 xff0c 从数据库提取XML 顺利通过 下午 xff1a 一键还原电脑 xff0c 重新打开VS2010运行程序 xff0c 从数据库提取XML报错 根级别上的数据无效 行 1 xff0c 位置
  • 接触客户、接触业务、来谈我的感触

    很久没有做工作总结 xff0c 今天记录下我今年接触客户的一些感触 以前是一个刚入门的开发新人 xff0c 刚进公司感觉公司的开发能力不行 xff0c 没有一套成熟的框架 xff0c 没有美工 xff0c 已经开发出的软件界面很丑 自己开发
  • 编写一个函数,判断用户传入的对象(字符串,列表,元组)长度是否大于10

    span class token keyword def span span class token function my object span span class token punctuation span n span clas
  • 双盘(一个固态硬盘+机械硬盘(efi格式)+2080TI) 安装: ubuntu16.04+显卡驱动+cuda10.2+pytorch

    详细步骤 xff1a 从零开始配一个深度学习服务器 xff1a 固态 43 机械双硬盘ubuntu系统的安装 分区 配置超详细教程 it610 com 一 系统安装 Ubuntu6 04安装 UEFI 43 GPT双硬盘安装Win10 43
  • Idea java.lang.ClassNotFoundException: org.slf4j.LoggerFactory 报错

    系统想用slf4j记录日志 xff0c 可是程序编译的时候报错 xff1a java lang ClassNotFoundException org slf4j LoggerFactory 检查了POM依赖和Jar包 xff0c 都没有问题
  • 小米2020校招软件开发工程师笔试题一

    1 下列关于设计模式说法错误的是 xff08 B xff09 A 装饰器模式在实现过程中一般不会更改被封装对象的接口定义 B 适配器模式以不改变被适配对象的接口定义为目的对其进行改造 C 用饿汉方式实现的单例模式是不能够被继承的 D 简单工
  • vscode1.70.2 添加终端 powershell7

    前提已经安装号powershell7 xff0c 并且已经添加到系统环境中 如何测试是否配置成功呢 xff0c 在运行中输入pwsh xff0c 点击确定后能打开powershell7就说明成功了 打开vscode的设置 xff0c 搜索
  • twm配置文件.twmrc

    系统的twmrc文件位于 usr X11 twm目录下 xff0c 为system twmrc xff0c 但是修改这个文件是不生效的 xff0c 必须将这个文件拷到 HOME下 xff0c 重命名为 twmrc才生效 twm有一个特别奇怪
  • Redis缓存型数据库实现秒杀库存加减

    多线程并发下商品库存递减或者抢购商品数量累加 xff0c 可以使用increment 方法 通常使用异步的方式 xff0c 前端 61 gt 用户抢购处理 61 gt 缓存 61 gt 队列 61 gt 持久化 xff0c 可以使用入队列的
  • Java项目:医院住院管理系统(java+SSM+JSP+bootstrap+mysql)

    源码获取 xff1a 俺的博客首页 34 资源 34 里下载 xff01 项目介绍 本项目有多种角色 xff0c 包含管理员 用户 护士 服务前台等角色 由于篇幅限制 xff0c 只截图了管理员角色的功能 管理员角色主要功能包括 xff1a
  • 直接使用X11输出图像的方法

    直接使用X11输出图像有两种方法 xff0c 一种是使用XImage xff0c 另一种是使用Pixmap XImage是本地对象 xff0c 而Pixmap是XServer端对象 特别要注意的是X11中Bitmap是黑白位图的意思 xff
  • python文件读写的缓冲行为

    文件的io操作的缓冲行为分为 全缓冲 xff1a 同系统及磁盘块大小有关 xff0c n个字节后执行一次写入操作 行缓冲 xff1a 遇到换行符执行一次写操作 无缓冲 xff1a 立刻执行写操作 open 函数 help open Help
  • 在Linux中使用systemctl如何管理Systemd服务和单元

    Systemctl是一个systemd工具 xff0c 它负责控制systemd系统和服务管理程序 Systemd是一个系统管理守护进程 xff0c 工具和库的集合 xff0c 它用作替换System V init守护进程 Systemd功
  • iOS中的viewpager,开源库WMPageController在storyboard中的使用

    http blog csdn net yubo 725 article details 51159633 关于WMPageController的使用以上链接写的很清楚 xff0c 在此感激博主 android 中有viewpager xff
  • 约瑟夫环问题研究(一)

    最近在看C方面的东西 xff0c 看到了李明老师讲解的约瑟夫环问题 xff0c 感觉很有意思 xff0c 于是在看了他的讲解之后 xff0c 自己又重新按照他的思路进行了编写 xff0c 整理如下 xff1a 问题描述 xff1a 约瑟夫环