其他分享
首页 > 其他分享> > 赵大超的学习周志(一)

赵大超的学习周志(一)

作者:互联网

转:

赵大超的学习周志(一)

赵大超的学习周志(一)

本周是Java基础学习的第一周,学习内容包括关键字与标识符、数据类型、运算符、标准输入、随机数、分支语句、循环语句、等内容,并对数组简单开了个头,其中大部分内容都在试学阶段学习过并基本掌握,所以学习起来较为轻松。在最后一天数组的相关练习中有两道题有所难度,记录研究如下:

一、约瑟夫环问题

题目:有500个人围城一个圈,依次报数,每数到3的倍数的人离开圈,数完一圈后继续从1开始数,直到圈中剩下最后一个人,求剩下的人原来在圈中的位置(约瑟夫环问题)

实现逻辑:
实现关键在于如何表示参与游戏者是否被淘汰,以及如何实现围圈报数,并且需要记录最终获胜者为第几人。可以用元素所存值来记录游戏玩家的状态,如值为0则表示未被淘汰,如被淘汰则将元素值改为1,表示已被淘汰,在游戏报数前先对玩家状态进行判断,若已被淘汰则不进入游戏,若未被淘汰则进行报数操作,判断报数为3的倍数则被淘汰,报数+1,数组下标+1,进入下一次循环。每次不论当前下标的元素是否被淘汰,都需要使下标自增以保证轮到下一下标的元素进行判断,保证游戏正常进行,每当下标进行到数组长度-1处时,下一次则要轮到下标为0的元素进行判断,以保证实现围圈报数的效果。最后当剩余一人未被淘汰时结束循环,记录该玩家对应数组的下标,胜利者即为第下标+1个人。
①由500人围圈报数,则定义一个长度为500的数组,不赋值则初始值默认为0,则设定元素值为0表示未被淘汰状态,值为1为淘汰状态。
②定义变量count初值为数组长度,表示未淘汰人数;定义变量num初值为1,表示当前所报的数;定义变量index初值为0,用于记录当前元素的下标。
③使用循环进行游戏,当未淘汰人数等于1时结束循环;循环判断当前下标元素是否被淘汰,若被淘汰则判断当前元素是否为最后一个玩家,若是则重新将index置0开始即可从下一圈继续报数,若否则将index+1对下一个元素进行判断;若未被淘汰则进入游戏,判断当前元素所报数是否为3的倍数,若是3的倍数则将其状态由0置1表示被淘汰,并将count-1以减少一个未被淘汰人数;之后判断当前元素是否为最后一个玩家,操作如上,最后将num+1作为下个人报的数,index+1进入下一个元素的判断。
④循环遍历数组元素值,当元素值为0是退出循环,记录当前下标索引,获胜者则为第该下标+1人。

代码实现:

	//定义数组
	int[] arr = new int[500];
	//未被淘汰人数
	int count = arr.length;
	//当前已报数
	int num = 1;
	//当前数组索引
	int index = 0;
	
	//未淘汰人数仅剩1人时退出循环
	while(count != 1) {
		//未被淘汰则参与游戏
		if(arr[index] == 0) {
			//报数被3整除
			if(num % 3 == 0) {
				//状态置1,淘汰
				arr[index] = 1;
				//未淘汰人数-1
				count --;
			}
			//若当前报数人为最后一人
			if(index == arr.length - 1) {
				//下标置0,实现围圈报数
				index = 0;
				//下一任所报数
				num ++;
				//跳出本次进入下次循环
				continue;
			}
			//下一任所报数
			num ++;
			}else{  //若为已被淘汰者
				if(index == arr.length - 1) {
					index = 0;
					continue;
				}
			}
		//下标+1,保证游戏向下进行
		index ++;
	}
	
	int i;
	for (i = 0; i < arr.length; i++) {
		//找出未淘汰者则记录下标,退出循环
		if(arr[i] == 0) {
			break;
		}
	}
	//胜利者为第该下标+1人
	System.out.println("第" + (i + 1) + "个玩家获得胜利");

然后我对比了一下以前老师写的约瑟夫环代码,如下:

// 约瑟夫环
		Scanner scanner = new Scanner(System.in);
		// 确定游戏参数
		System.out.print("请输入参与人数:");
		int n = scanner.nextInt();
		System.out.print("请输入淘汰数值:");
		int outN = scanner.nextInt();

		// 定义一个数组保存玩家的状态: 0-未淘汰 1-淘汰
		int[] states = new int[n];

		// 定义一个变量记录当前玩家所报的数
		int number = 0;
		// 定义一个变量纪录玩家的下标
		int index = 0;

		while (true) {
			// 如果玩家没有被淘汰,则进入游戏报数
			if (states[index % states.length] == 0) {
				// 如果玩家报的数等于淘汰值,则淘汰玩家
				if (++number == outN) {
					// 修改玩家状态,让玩家淘汰出局
					states[index % states.length] = 1;
					// 玩家淘汰,游戏人数-1,判定游戏是否结束
					if (--n == 1) {
						break;
					}
					// 游戏继续,重置报数值
					number = 0;
				}
			}
			// 游戏继续,让后一个玩家继续游戏
			index++;
		}

		for (int i = 0; i < states.length; i++) {
			if (states[i] == 0) {
				System.out.println("第" + (i + 1) + "个玩家取得胜利!");
				break;
			}
		}

对比后发现自己的代码可以进行如下改进:
实现围圈报数时我是将索引重新置0来实现,而老师则是将索引对数组长度进行取余,所得即为下一圈报数元素的索引,也避免了每次对索引是否超过数组长度情况的判断,更加简洁和巧妙。

二、如何输出由键盘输入元素的字符串

题目:定义一个数组,由键盘输入值来赋值,并输出该数组的各值

实现逻辑:
老师设计题目时应该只是想定义一个已知长度的数组,再将输入的元素赋给数组,但我在实现时给自己加了点难度,一个是将数组以字符串的形式输入以查看,如何确定数组长度或者说以字符串形式输出数组时如何能够只输出自己输入的值,不输出默认初始化的空值“0”;另一个是如何实现使用户结束输入元素。数组长度采取解决的方案是先创建一个足够大的数组用来初步存放数组,或定义一个动态数组,即先定义一个较小的数组,当数值个数超过数组长度时则再创建一个长度为当前长度的1.5倍的数组,第一种方式的缺点就是长度可能存在不够的现象且当初始化时定义的长度过长会浪费内存,所以使用第二种方法动态数组更好,本次为了方便简介就先使用第一种方法定义长度为1000,动态数组的实现代码下次再贴出。如何结束键盘输入数组采取的方法是在提示用户输入整数时同样提示用户输入“over”以结束输入,然后以Scanner.nextLine()方法接收元素,若为整数则将之存入数组,若为“over”则跳出循环不再输入,并记录存数次数。得到数组为带有空值“0”的数组,若想让数组长度就为输入元素个数长度时则创建一个新数组数组长度为刚才输入值时记录的输入次数值即可。输出时有两种方式,若只是将原数组中非空值“0”输出的话可以使用字符串拼接方式,也可以使用Arrays.toString()方法进行输出。

代码如下:

Scanner sc = new Scanner(System.in);
		/*	
		 * 	尽量将数组长度定义的大些保证够用,确定是浪费空间内存
		 * 	也可以先定义一个长度较小数组,
		 * 	再编写一个长度不足时增加一半数组长度的方法进行调用
		 */
		int[] tempArr = new int[1000];
		int count = 0;
		String str = null;
		System.out.println("输入存入数组的值(输入"over"结束输入):");
		
		for (int i = 0; i < tempArr.length; i++) {
			str = sc.nextLine();
			//当比较引用数据类型的值时使用equals方法,直接使用"=="比较的话比较的是引用地址
			if(str.equals("over")) {
				break;
			}
			tempArr[i] = (Integer.parseInt(str));
			count ++;
		}
		System.out.print("生成的数组为:[");
		
		/*	
		 * 	若要使新数组没有初始化的值,即数组长度等于用户输入数的次数,
		 * 	则定义新数组,通过循环将老数组中非0值(指初始化的0,手动输入的0不影响)传入其中,
		 * 	使用循环方式输出数组中非0(指初始化的0,手动输入的0可以输出)的数
		 * 	也采用Arrays.toString()方法以字符串形式输出新数组
		 */
		int i = 0;
		while(i < count) {
			System.out.print(tempArr[i ++]);
			if(i != count) 
			System.out.print(",");
		}
		System.out.print("]");
		
		int[] arr = new int[count];
		

在代码实现时遇到的问题是:判断是否输入了字符串“over”时的判断条件写的是if(str == “over”),运行时输入“over”后报错,经过debug调试后发现,当进行 str == “over” 的判断时并不符合,导致不跳出循环而是继续将"over"转为int型失败,故报错。由此发现引用类型对值进行比较时不能使用"=="进行比较,这样比较的是两个引用地址值,所以不会满足条件跳出循环。查询后发现应使用String的equals()方法进行值的比较,使用后满足条件,程序正常执行。

转:

赵大超的学习周志(一)

标签:index,下标,int,周志,赵大超,学习,数组,淘汰,报数
来源: https://www.cnblogs.com/wangtcc/p/14698866.html