今天在群里看到一道面试题,做了两种解法

题目如下:

现有1000人,一字排开,开始报数,第一轮报偶数的出局,报基数的人留下,留下的人重新报数,第二轮报基数的出局,报偶数的留下,留下的人重新报数,第三轮同第一轮一样报偶数的出局,报基数的人留下,留下的人重新报数,第四轮同第二轮一样报基数的出局,报偶数的留下。依次轮流,基数次报数留报基数的人,偶数次报数留报偶数的人。最后留下一个人,请问这个人在第一次报数时报的是多少?

两种解法,解法2是朋友想出

解法1:

// 链表
		ArrayList list = new ArrayList(1000);
		for (int i = 1; i < 1001; i++) {
			list.add(i);
		}
		int qs = 1;
		while (true) {
			// 判断list大小是否为1 如果为1则循环结束
			if (list.size() == 1) {
				System.out.println("循环了" + qs + "圈最后剩下的数字" + list.get(0));
				return;
			}
			// 判断是否奇数圈,如果奇数圈移除偶数位的数字,否则移除奇数位的数字
			for (int k = 0; k < list.size(); k++) {
				if (k % 2 != 0 && qs % 2 == 1) {
					list.set(k, "0");
				} else if (k % 2 == 0 && qs % 2 == 0) {
					list.set(k, "0");
				}
			}
			for (int i = 0; i < list.size(); i++) {
				if ("0".equals(list.get(i))) {
					list.remove(i);
				}
			}
			qs++;// 圈数
		}

解法2:
		boolean delFalg = true;//圈数状态,如果是奇书圈则为真
		int count = 1000;//人数
		int[] mans = new int[1000];//定义一个长度为1000的数组,只用下标
		while (count > 1) {
			int l = 0;
			//循环减人
			for (int i = 0; i < mans.length; i++) {
				if (mans[i] == 1)//如果当前数组下标已经被赋予值,说明之前已经被减掉,跳过
					continue;
				l++;
				//如果符合奇数圈偶数位或者偶数圈奇数位将数据组对应下标赋值
				if (delFalg && l % 2 == 0 || !delFalg && l % 2 != 0) {
					mans[i] = 1;
					count--;
				}
			}
			delFalg = !delFalg;//每次循环反转状态,用来标志奇偶圈数
		}
		//找出下标位对应值为0的数组下标 它的所在位数就是对应第一次叫的数字
		for (int i = 0; i < mans.length; i++) {
			if (mans[i] == 0) {
				System.out.println("剩下的人的第一次报数为:" + (++i));
				break;
			}
		}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值