头条校招(今日头条2017秋招真题)
题目描述
头条的2017校招开始了!为了这次校招,我们组织了一个规模宏大的出题团队。每个出题人都出了一些有趣的题目,而我们现在想把这些题目组合成若干场考试出来。在选题之前,我们对题目进行了盲审,并定出了每道题的难度系数。一场考试包含3道开放性题目,假设他们的难度从小到大分别为a, b, c,我们希望这3道题能满足下列条件:
a<= b<= c
b - a<= 10
c - b<= 10
所有出题人一共出了n道开放性题目。现在我们想把这n道题分布到若干场考试中(1场或多场,每道题都必须使用且只能用一次),然而由于上述条件的限制,可能有一些考试没法凑够3道题,因此出题人就需要多出一些适当难度的题目来让每场考试都达到要求。然而我们出题已经出得很累了,你能计算出我们最少还需要再出几道题吗?
输入
输入的第一行包含一个整数n,表示目前已经出好的题目数量。 第二行给出每道题目的难度系数 d1, d2, …, dn。 |
样例输入
4 20 35 23 40 |
输出
输出只包括一行,即所求的答案。 |
样例输出
2 |
时间限制
C/C++语言:1000MS
其它语言:3000MS
|
内存限制
C/C++语言:65536KB
其它语言:589824KB
|
这道题我的解题思路是:因为只要凑够三道满足要求的题目就可以进行一次考试,所以我创建一个容量最大为3的桶,通过不断往里面添加满足要求的元素,当桶满时,就能进行一次考试。然后将桶清空,再次重复之前的过程。这是一种贪心的策略。在做这道题时要先对输入元素进行从小到大的排序。这道题难点在于要解决下面的这些情况:
输入用例1:1 2 3 10 20 40 50
输入用例2:10 100 200
废话不说,直接贴代码吧:
import java.util.Collections;
import java.util.LinkedList;
import java.util.Scanner;
public class XiaozhaoTT {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
LinkedList<Integer> factor = new LinkedList<Integer>(); //这是存放难度系数的链表
for (int i = 0; i < n; i++)
factor.add(scanner.nextInt());
Collections.sort(factor); // 对难度系数链表中的元素进行排序
Bucket bucket = new Bucket();//创建一个最大容量为3的桶
int count = 0;//对还需要出几道题进行计数
int before = 0; //用来表示已加入桶中的元素
while (!factor.isEmpty()) { //不断把链表中的东西取出来,直到为空
if (bucket.isFull()){
bucket.clear(); //如果桶满了,清空桶。
continue;
}
if (bucket.isEmpty()) { //当桶是空的时候,直接添加元素进入桶
before = factor.removeFirst();
bucket.add(before);
continue;
}
//当桶既不空也不满时,执行下列操作
int distance = factor.get(0) - before;
if (distance <= 10) {
before = factor.removeFirst();
bucket.add(before);
} else {
//若桶中已经装入的元素与链表中的任何元素的差都大于10,
//则人为添加一个与桶中最大元素相差10的元素,count++
before += 10;
bucket.add(before);
count++;
}
}
//有可能出现这种情况,当输入为1 2 3 4 5时,按照上面的步骤,最后桶中可能有两个元素4和5,
//这时需要把桶装满
while (!bucket.isEmpty() && !bucket.isFull()) {
before += 10;
bucket.add(before);
count++;
}
System.out.println(count);
}
public static class Bucket { // 这是一个容量最大为3的桶
LinkedList<Integer> lt = new LinkedList<Integer>();
public boolean isFull() { //是否桶满了
return lt.size() == 3 ? true : false;
}
public boolean isEmpty() { //桶是否为空
return lt.isEmpty() ? true : false;
}
public void add(Integer i) { //往桶中添加元素
lt.add(i);
}
public void clear() { //将桶清空
lt.clear();
}
}
}
运行结果图
其实在做这道题之前我和同学讨论过,我们曾提出用图论的做法来解决这道题:把难度系数看成一个个结点,当两个结点间的值差小于或等于10,这两个节点有边,然后题目就转化成寻找有三个结点或三个结点的倍数的树,通过补充结点的方法把图构建成若干个3n结点的树即可,输出的是补充结点的数目。然而,我感觉这个编程难度有点大,所以没有具体尝试,而且在其中有些问题没有想明白,不知道读者有没有更好的方法,希望能在下方给我留言!谢谢!