赛码网算法

**

赛码网算法 军训队列

题目描述

某大学开学进行军训队列训练,将学生从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列剩下的依次向前靠拢,再从头开始进行一至三报数,凡报到三的出列,剩下的依次向前靠拢,继续从头开始进行一至二报数。。。以后每次从头开始轮流进行一至二报数、一至三报数直到剩下的人数不超过三人为止。
link.
输入输出格式

心路历程

第一次做这种传统oj。哇刚看到这道题,结合题目和输入输出,整个都给看蒙了,不知道输入输出和题目有啥关系,感觉赛码真的和leetcode,牛客差好多,题目描述一大堆。。。。看了真的是半天(绝不虚假的时间)也没看太懂,最后还是自己动手在纸上比划终于读懂题意了。

题目分析

样例输入
2
20
40
样例输入中的2代表两组学生,接下来的20,40分别代表第一组,第二组学生人数。以第一组20个学生为例,
第一次报数(报到二的出列)后剩下的学生的原始编号为:1,3,5,7,…,17,19
第二次报数(报到三的出列)后剩下的学生的原始编号为:
1,3,7,9,13,15,19
第三次报数(报到二的出列)后剩下的学生的原始编号为:
1,7,13,19
第四次报数(报到三的出列)后剩下的学生的原始编号为:
1,7,19
此时剩下的人数不超过三了,算法结束可以输出了

思路

首先取出输入的第一行整数N,然后对接下来的N条输入分别进行处理:分别根据每一行中的整数n创建相应大小的int数组,将学生编号放入该数组中,再依次循环对数组进行二次出队,三次出队的操作。注意使用到了clone()方法。

代码

膜一膜某大神的简洁代码,加了自己的注释理解

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int N = scanner.nextInt(); //输入学生的组数
		for (int i = 0; i < N; i++) { //读完输入的学生的组数
			int n = scanner.nextInt();//每组中的学生数
			int k = n; //用k来记录每次变化后的学生数
			int[] a = new int[n]; //创建学生数大小的int数组放置学生编号
			// 将学生编号放入数组中
			for (int j = 0; j < a.length; j++) {
				a[j] = j + 1;
			}
			while (k > 3) {//一次报数后剩下的人数是否小于3
				k = k - k / 2; //报道2出队之后的学生数
				a = oq(k, a, 2);
				if(k>3){ //如果此时人数还是大雨3,就让剩下的报到三的出队
					k = k - k / 3; //报道3出队之后的学生数
					 a= oq(k, a, 3);
				}else{
					break;
				}
			}
			for(int c = 0; c < a.length; c++){
				System.out.print(a[c] + " ");
			}
		}
	}

	private static int[] oq(int k, int[] a, int d) {//d取值为2或者3
		int[] b = a.clone(); //kelong数组
		a = new int[k]; //开辟k空间大小的数组a
		for (int t = 1, q = 0; t <= b.length; t++) {
			// ??
			if (t % d != 0) {
				a[q] = b[t-1];
				q++;
			}
		}
		return a;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值