很菜。只做起了一道,现在把第二道写起了,分享出来,我自测了一些案例,进不了科大讯飞,但是这个周五下午学了很多小知识点。
修改成绩
时间限制:C/C++语言 1000MS;其他语言 3000MS 内存限制:C/C++语言 65536KB;其他语言 589824KB
题目描述:
华老师的n个学生参加了一次模拟测验,考出来的分数很糟糕,但是华老师可以将成绩修改为[0,100]中的任意值,所以他想知道,如果要使所有人的成绩的平均分不少于X分,至少要改动多少个人的分数?
输入
第一行一个数T,共T组数据(T≤10)
接下来对于每组数据:
第一行两个整数n和X。(1≤n≤1000, 0≤X≤100)
第二行n个整数,第i个数Ai表示第i个学生的成绩。(0≤Ai≤100)
输出
共T行,每行一个整数,代表最少的人数。
样例输入
2
5 60
59 20 30 90 100
5 60
59 20 10 10 100
样例输出
1
2
Hint
对于第一组数据,将59改成60即可
我的答案,有些关键注释
public class CountNum {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
int DataNum = Integer.valueOf(scanner.nextLine());
int[] outputNum = new int[DataNum];
int key = 0;
for (int i = 0; i < DataNum; i++) {
String[] inputSs = scanner.nextLine().split(" ");
int StudentNum = Integer.parseInt(inputSs[0]);
int Average = Integer.parseInt(inputSs[1]);
String[] inputSs2 = scanner.nextLine().split(" ");
//先将输入的成绩排序
int[] gardes = sortGarde(inputSs2);
//把每组数据需要修改的数据计算出来,存在数组里,统一输出
int num = countNun(gardes,StudentNum,Average);
outputNum[key] = num;
key++;
}
for (int i = 0; i < key; i++) {
System.out.println(outputNum[i]);
}
}
//计算每组数据的修改成绩个数
private static int countNun(int[] gardes, int studentNum, int average) {
// TODO Auto-generated method stub
int nowAverage = 0;
int num = 0;
for(int i = 0; i<gardes.length;i++){
nowAverage = nowAverage +gardes[i];
}
//如果直接大于平均成绩了
if (nowAverage/studentNum >= average) {
return num;
}else {
//如果小于平均成绩,每次都把最小的那个数改成平均值,在求当前平均数
for(int i = 0; i<gardes.length;i++){
nowAverage = nowAverage - gardes[i] + average ;
num++;
if (nowAverage/studentNum >= average) {
return num;
}
}
}
return studentNum;
}
//给输入的成绩排序,便于修改成绩(从最小的开始改)
private static int[] sortGarde(String[] inputSs2) {
// TODO Auto-generated method stub
int[] gardes = new int[inputSs2.length];
for(int i = 0; i<inputSs2.length;i++){
int min = Integer.valueOf(inputSs2[i]);
int key = i;
for(int j = inputSs2.length-1; j >= i;j--){
int b = Integer.valueOf(inputSs2[j]);
if (min > b) {
min = b;
key = j;
}
}
String a = inputSs2[i];
inputSs2[i] = min+"";
inputSs2[key] = a;
}
for (int i = 0;i< inputSs2.length;i++){
gardes[i] = Integer.valueOf(inputSs2[i]);
}
return gardes;
}
}
杀手
时间限制:C/C++语言 1000MS;其他语言 3000MS 内存限制:C/C++语言 65536KB;其他语言 589824KB
题目描述:
有n个杀手排成一行,每个杀手都有一个不同的编号(编号为1-n),在每个夜晚,杀手都会行动,如果某个杀手编号大于他右边的杀手的编号,他就会杀死他右边的杀手,杀手是的行动是瞬间的,因此一个人可能某一个夜晚既杀死了别人又被别人杀死,例如3,2,1这个顺序,在第一个夜晚2会杀死1,同时3也会杀死2。
显而易见,一段时间之后,就不会有人杀或被杀,平安夜也就到来了,请问在平安夜之前有多少个夜晚。
输入
输入第一行是一个整数n(1≤n≤100000),表示杀手的数量。
接下来一行有n个数,是一个1-n的全排列。
输出
输出包含一个整数,表示平安夜之前经历了多少个夜晚。
样例输入
10
10 9 7 8 6 5 3 4 2 1
样例输出
2
Hint
补充样例
输入样例2
6
1 2 3 4 5 6
输出样例2
0
样例解释:
样例1中杀手的变化为[10 9 7 8 6 5 3 4 2 1]->[10 8 4]->[10],故答案为2。
我的解答
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
public class CountDay {
public static void main(String[] args) {
// TODO Auto-generated method stub
int day = 0; //最后天数
int killnum = 0; // 杀人数量,用于判断轮询几次
Scanner scanner = new Scanner(System.in);
int KillerNum = Integer.valueOf(scanner.nextLine());
List<Integer> killer = new ArrayList<>(); //总杀手
// 每次杀了哪些人的位置,便于从总人数里面remove掉
List<Integer> killindex = new ArrayList<>();
String[] inputSs = new String[KillerNum];
inputSs = scanner.nextLine().split(" ");
for (int i = 0;i< KillerNum;i++){
killer.add(Integer.valueOf(inputSs[i]));
}
while(true){
//两两相邻比较,如果前>后,后者被杀,用killindex记录被杀的位置
for(int i = 0; i<= KillerNum-2-killnum; i++){
if (killer.get(i) > killer.get(i+1)) {
killindex.add(i+1);
}
}
//将被杀人的位置从大到小排序,依次remove
//!之所以这样做的目的是,需要先remove最大的,保证前面的位置不会变化
Collections.sort(killindex,Collections.reverseOrder());
for(int i = 0; i<killindex.size();i++){
//不直接killer.remove(Integer.valueOf(killindex.get(i)));的原因:
//remove(index)和remove(obj)优先考虑obj
int j = Integer.valueOf(killindex.get(i));
killer.remove(j);
killnum++;
}
//如果本次killindex没值,代表人已经杀光了
if (killindex.size() == 0) {
break;
}
day++;
killindex.clear();
}
System.err.println(day);
}
}
总结
我看到网上有更好的方法,我很多地方用了比较笨的方法,但是自己思路写起还不错!