2019校招真题编程练习 - 1
文章目录
题目描述
为了找到自己满意的工作,牛牛收集了每种工作的难度和报酬。牛牛选工作的标准是在难度不超过自身能力值的情况下,牛牛选择报酬最高的工作。在牛牛选定了自己的工作后,牛牛的小伙伴们来找牛牛帮忙选工作,牛牛依然使用自己的标准来帮助小伙伴们。牛牛的小伙伴太多了,于是他只好把这个任务交给了你。
输入描述
每个输入包含一个测试用例。
每个测试用例的第一行包含两个正整数,分别表示工作的数量N(N<=100000)和小伙伴的数量M(M<=100000)。
接下来的N行每行包含两个正整数,分别表示该项工作的难度Di(Di<=1000000000)和报酬Pi(Pi<=1000000000)。
接下来的一行包含M个正整数,分别表示M个小伙伴的能力值Ai(Ai<=1000000000)。
保证不存在两项工作的报酬相同。
输出描述
对于每个小伙伴,在单独的一行输出一个正整数表示他能得到的最高报酬。一个工作可以被多个人选择。
示例
输入
3 3
1 100
10 1000
1000000000 1001
9 10 1000000000
输出
100
1000
1001
思路
在工作难度小于等于自身能力的工作中,选择其中最高的报酬。
解题思路
将工作难度与报酬输入一个二维数组jobs,将能力值与员工编号输入一个数组people。
将工作报酬按报酬从大到小排序,根据员工能力值与工作难度进行比较,因为报酬从大到小排序,所以按照当数组自增jobIdx遍历工作难度时,满足(工作难度<能力值)条件的第一个工作难度对应的报酬一定是最大的,此时拿到该员工编号与工作报酬的值,people++;否则增加jobIdx
import java.util.Scanner;
import java.util.Arrays;
import java.util.Comparator;
public class Main{
public static void main(String[] args){
Scanner s = new Scanner(System.in);
int N = s.nextInt();
int M = s.nextInt();
if(N < 1 || M < 1)
return;
int[][] jobs = new int[N][2];
int[][] people = new int[M][2];
for(int i=0; i<N; i++){
jobs[i][1] = s.nextInt();
jobs[i][0] = s.nextInt();
}
//jobs逆序排序
Arrays.sort(jobs, (int[] a1,int[] a2)->{
if(a1[0]<a2[0])
return 1;
else if (a1[0]>a2[0])
return -1;
else
return 0;
});
for(int i=0; i<M; i++){
people[i][0] = s.nextInt();
people[i][1] = i;
}
//people逆序排序
Arrays.sort(people, (int[] a1,int[] a2)->{
if(a1[0]<a2[0])
return 1;
else if (a1[0]>a2[0])
return -1;
else
return 0;
});
int jobIdx = 0, peopleIdx = 0;
int[] result = new int[M];
while(peopleIdx < M && jobIdx < N){
if(jobs[jobIdx][1] <= people[peopleIdx][0]){
result[people[peopleIdx][1]] = jobs[jobIdx][0];
peopleIdx++;
}else
jobIdx ++;
}
for (int i = 0; i < M; i++)
System.out.println(result[i]);
}
}
· Arrays.sort()
import java.util.Arrays;
Java的Arrays类中有一个sort()方法,该方法是Arrays类的静态方法,在需要对数组进行排序时,非常的好用。
1)Arrays.sort(int[] a)
对一个数组的所有元素进行排序,并且是按从小到大的顺序。
import java.util.Arrays;
public class Main{
public static void main(String[] args){
int[] a = {9, 8, 7, 2, 3, 4, 1, 0, 6, 5};
Arrays.sort(a);
for(int i=0; i<a.length; i++){
System.out.print(a[i]+ " ");
}
}
}
运行结果:
0 1 2 3 4 5 6 7 8 9
2)Arrays.sort(int[] a, int fromIndex, int toIndex)
对数组部分排序,也就是对数组a的下标从fromIndex到toIndex-1的元素排序. [fromIndex, toIndex)
注意:下标为toIndex的元素不参与排序哦!
import java.util.Arrays;
public class Main{
public static void main(String[] args){
int[] a = {9, 8, 7, 2, 3, 4, 1, 0, 6, 5};
Arrays.sort(a, 0, 3);
for(int i=0; i<a.length; i++){
System.out.print(a[i]+ " ");
}
}
}
运行结果:
7 8 9 2 3 4 1 0 6 5
3) Arrays.sort(T[] array, int fromIndex, int toIndex, Comparator c)
可实现从大到小的排序。
注意,要想改变默认的排列顺序,不能使用基本类型(int,double, char)
而要使用它们对应的类(Integer)
Comparator
在java中,如果要对集合对象或数组对象进行排序,需要实现Comparator接口以达到我们想要的目标。
import java.util.Arrays;
import java.util.Comparator;
public class Main{
public static void main(String[] args){
Integer[] a = {9, 8, 7, 2, 3, 4, 1, 0, 6, 5};
Comparator cmp = new MyComparator();
Arrays.sort(a,cmp);
for(int i=0; i< a.length; i++){
System.out.print(a[i] + " ");
}
}
}
class MyComparator implements Comparator<Integer>{
@Override
public int compare(Integer n1, Integer n2){
//如果n1小于n2,我们就返回正值,如果n1大于n2我们就返回负值:从大到小排序
//颠倒:从小到大
if(n1<n2){
return 1;
}else if (n1>n2){
return -1;
}else
return 0;
}
}
或
String[] data = {"1", "4", "3", "2"};
System.out.println(Arrays.toString(data)); // [1, 4, 3, 2]
// 实现降序排序,返回-1放左边,1放右边,0保持不变
Arrays.sort(data, (str1, str2) -> {
if (str1.compareTo(str2) > 0) {
return -1;
} else {
return 1;
}
});
System.out.println(Arrays.toString(data)); // [4, 3, 2, 1]
哈希表
数组:采用一段连续的存储单元来存储数据。对于指定下标的查找,时间复杂度为O(1);通过给定值进行查找,需要遍历数组,逐一比对给定关键字和数组元素,时间复杂度为O(n),当然,对于有序数组,则可采用二分查找,插值查找,斐波那契查找等方式,可将查找复杂度提高为O(logn);对于一般的插入删除操作,涉及到数组元素的移动,其平均复杂度也为O(n)
线性链表:对于链表的新增,删除等操作(在找到指定操作位置后),仅需处理结点间的引用即可,时间复杂度为O(1),而查找操作需要遍历链表逐一进行比对,复杂度为O(n)
二叉树:对一棵相对平衡的有序二叉树,对其进行插入,查找,删除等操作,平均复杂度均为O(logn)。
哈希表:相比上述几种数据结构,在哈希表中进行添加,删除,查找等操作,性能十分之高,不考虑哈希冲突的情况下(后面会探讨下哈希冲突的情况),仅需一次定位即可完成,时间复杂度为O(1),接下来我们就来看看哈希表是如何实现达到惊艳的常数阶O(1)的。
数据结构的物理存储结构只有两种:顺序存储结构和链式存储结构(像栈,队列,树,图等是从逻辑结构去抽象的,映射到内存中,也这两种物理组织形式),而在上面我们提到过,在数组中根据下标查找某个元素,一次定位就可以达到,哈希表利用了这种特性,哈希表的主干就是数组。