牛牛举办了一次编程比赛,参加比赛的有3*n个选手,每个选手都有一个水平值a_i,现在要将这些选手进行组队,一共组成n个队伍,即每个队伍3人.牛牛发现队伍的水平值等于该队伍队员中第二高水平值。
例如:
为了让比赛更有看点,牛牛想安排队伍使所有队伍的水平值总和最大。
如样例所示:
如果牛牛把6个队员划分到两个队伍
如果方案为:
team1:{1,2,5}, team2:{5,5,8}, 这时候水平值总和为7.
而如果方案为:
team1:{2,5,8}, team2:{1,5,5}, 这时候水平值总和为10.
由于没有比总和为10更大的方案,所以输出10.
分析:我们首先最容易想到的是把每一位选手的水平值存入到一个数组当中,并且将它们排序
水平值 | 1 | 2 | 5 | 5 | 5 | 8 |
---|---|---|---|---|---|---|
下标 | 0 | 1 | 2 | 3 | 4 | 5 |
本题的主要思路是贪心算法
贪心算法 其实很简单,就是每次选值时都选当前能看到的局部最解忧,所以这里的贪心就是: 保证每组的第二个值取到当前能选择的最大值就可以,我们每次尽量取最大,但是最大的数不可能是中间的数,所以退而求其次,取 每组中第二大的
所以我们这样分配:每次取当前数组的第一个元素和倒数最后两个元素进行组合形成新的分配组合
水平值 | 1 | 5 | 8 | 2 | 5 | 5 |
---|---|---|---|---|---|---|
下标 | 0 | 4 | 5 | 1 | 2 | 3 |
已分配好组合的中间值下标 = arr.length - 2 * (i + 1);
这个 i 是小于队伍数量的 即 i < n ;
然后我们便可以开始完成代码的书写
注意:在提交过程中可以使用int型进行存储运动员的水平值,但是提交代码后会发现只能通过60%的测试用例,分析用例可以得出:给出的测试用例已经超过了int的范围,所以需要考虑long型进行存储。
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
while(in.hasNextInt()) {
int n = scan.nextInt();
long[] arr = new long[3*n];//利用数组存放选手水平值
for(int i = 0; i < 3*n; i++) {
arr[i] = scan.nextLong();
}
Arrays.sort(arr);//将水平值从大到小进行排序,每次需要取次大的值(并不是按顺序取)
long sum = 0;
for(int i = 0; i < n; i++) {
sum += arr[arr.length - (2*(i+1))];//通过分析题目信息得到的取最大水平值的公式
}
System.out.println(sum);
}
}
}
输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。例如,输入
”They are students.”和”aeiou”
,则删除之后的第一个字符串变成”Thy r stdnts.”
这道题我们可以用 哈希映射 的思想来解(通过map实现)
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
String str1 = scanner.nextLine();
String str2 = scanner.nextLine();
HashMap<Character,Integer> map = new HashMap<>();
String ret = "";
//先遍历第二个数组
for(int i = 0; i< str2.length();i++){
if(map.get(str2.charAt(i)) == null){
//该字符不存在与map中
map.put(str2.charAt(i),1);
}else{
map.put(str2.charAt(i),map.get(str2.charAt(i))+1);
}
}
//再遍历第一个数组
for(int i = 0; i< str1.length(); i++){
if(map.get(str1.charAt(i)) == null){
ret = ret+str1.charAt(i);
}
}
System.out.println(ret);
}
}