百济神州后端开发工程师 - 部分笔试题 - 解析
选择题
1.下面关于Java中异常相关的说法错误的是(A)
A.编译时异常是在编译时期间发生的异常,不需要强制处理,但可以选择性地处理
B.Java中,所有异常类的顶层父类为Throwable类
C.在 try-catch 块中,多个catch块按照它们声明的顺序进行匹配,只有第一个匹配到的catch块会被执行,其他的会被忽略
D.应该将特定异常类型的catch块放在前面,将更通用的异常类型的catch块放在后面
2.下面 Java 代码的运行结果为( D )
public class Test {
public static void main(String[] args){
System.out.println(5 && 4);
}
}
A.运行错误
B. 4
C.5
D.编译错误
3.下面关于 Java 中的内部类说法错误的是( C )
A.匿名内部类没有名字,常用于实现接口或继承父类的匿名子类
B.内部类可以访问外部类的私有成员
C.局部内部类可以直接访问所在方法的局部变量
D.静态内部类不需要依赖于外部类实例,可以直接创建
解析:
在Java 8之前, 局部内部类只能访问所在方法的 final 修饰的局部变量。 Java 8 开始可以访问 effectively final (即一旦初始化就不可改变)的局部变量。
4.下面 Java 代码的运行结果为(编译错误)
interface Frob{
float v= 2.0f;
}
class Super{
int v=3;
}
public class Test extends Super implements Frob{
public static void main(String[] args){
new Test().printV();
}
void printV(){
System.out.println(v);
}
}
解析:
Test 类同时继承 Super 类并实现 Frob 接口,并且两者都有名为 v 的成员变量,导致编译器无法自动确定应该使用哪个 v,产生歧义。
5.下列关于数据字典说法错误的是?(AD)
A.数据字典可以将包含每个关系的记录的块存储在链表中
B.数据字典中存储有关系模式和关于关系的其他元数据
C.数据字典可能记录关系的存储组织及关系的存储位置
D.系统必须存储的信息类型不包括属性的域和长度
解析:
数据字典主要存储元数据信息,而不是将包含每个关系的记录的块存储在链表中。数据字典必须存储属性(列)的域(数据类型)和长度信息。
6.以下关于 DNS(Domain Name System)的说法中,错误的是(A)。
A.DNS 只能使用 UDP 协议进行通信,因为 UDP 协议的传输速度快,适合用于域名解析这种对实时性要求高的场景。
B.DNS 可以将域名解析为 IP 地址,使得用户可以通过易于记忆的域名来访问网络资源。
C.DNS 采用分布式的数据库结构,由多个 DNS 服务器协同工作,提高了系统的可靠性和可扩展性。
D.DNS 缓存可以加快域名解析的速度,但也可能导致解析结果不准确,因为缓存中的数据可能过期。
解析:
DNS 不仅可以使用 UDP 协议,还可以使用 TCP 协议,尤其是在需要传输较大 DNS 数据时。
7.现有一硬盘,其中磁盘转速是10000转/分,平均寻道时间是6ms,每个磁道包含800个扇区,则访问一个扇区的平均存取时间为( C )(结果保留两位小数)
A.11.21 ms
B.8.16 ms
C.9.01 ms
D.10.09 ms
解析:
平均存取时间 = 平均寻道时间 + 平均旋转延迟 + 数据传输时间
平均旋转延迟是磁头等待目标扇区旋转到其下方的平均时间。
硬盘转速为 10000 转/分,意味着每转耗时 60 秒 / 10000 转 = 0.006 秒/转 = 6 ms/转。
平均旋转延迟是旋转半圈的时间,所以平均旋转延迟为 6 ms/转 / 2 = 3 ms。
数据传输时间是磁头读取或写入一个扇区数据的时间。
每个磁道有 800 个扇区,所以转一圈可以读取 800 个扇区。
每个扇区的传输时间为: 6 ms/转 / 800 扇区/转 = 0.0075 ms/扇区。
因此,访问一个扇区的平均存取时间约为 9.0075 ms,保留两位小数后为9.01ms。
8.以下关于 RESTfuI API 的特性描述中,错误的是( A )。
A.强耦合性,客户端与服务器端紧密耦合。
B.无状态性,服务器不保存客户端的状态信息。
C.统一接口,使用标准的 HTTP 方法进行资源操作。
D.可缓存性,响应结果可以被缓存以提高性能。
解析:
RESTful API 的一个重要目标是实现松耦合,而不是强耦合。
9.在 Linux 中,以下哪个命令可以用于查看文件的前20行内容( C )
A.grep -20 filename
B.tail -20 filename
C.head -20 filename
D.cat -20 filename
10.在Linux系统中,有一个目录/projects,该目录下有多个子目录和文件。需要将/projects目录设置为:所有者可以读写执行,组用户可以读和执行,其他用户没有权限,同时确保子目录和文件继承该权限。假设当前权限未知,正确的命令是( B )
A. chmod -R u+rwx,g+rx /projects
B. chmod -R u=rwx,g=rx,o= /projects
C. chmod -R 740 /projects
D. chmod -R u+rwx,g+rx,o=/projects
解析:
C选项将 组用户的权限设置为 r-- (只读),而不是题目要求的 rx (读和执行)。AD选项使用了 + 添加权限,而非设置指定权限。
11.在一个医院管理系统中,已知分区的主存容量为180MB,初始阶段没有主存被占用(即为空),主存分配和释放的顺序(单位都为MB)为分配60,分配40,分配70,释放60,分配20,在采用最佳适应算法时,主存中最大空闲分区的大小是( C )
A.60MB
B.30MB
C.40MB
D.50MB
解析:
主存状态:[20MB (已用)], [40MB (空闲)], [40MB (已用)], [70MB (已用)], [10MB (空闲)]。
当前主存中的空闲分区大小分别为:40MB和10MB。因此,最大的空闲分区大小是 40MB。
12.下列属于文件扫描及索引选择方法的是( C )
I、线性搜索
II、聚集索引,码上等值比较
III、聚集索引,非码上的等值比较
IV、辅助索引,等值比较
A. II、III、IV
B.I、II、III
C.I、II、III、IV
D.I、III、IV
13.在一个游乐园过山车系统中,有6个进程共享一个互斥代码段,如果最多允许4个进程同时进入互斥段,那么信号量的初值为( D )
A.6
B.0
C.1
D.4
14.存在一组关键字序列{19,28,7,92,83,45,26,71},对该关键字序列进行直接插入排序,当把关键字26插入到对应的有序表中时,需要查找( A )次才能找到插入的位置。
A.5
B.2
C.3
D.4
解析:
插入 26:
比较 26 和 92 (1次)
比较 26 和 83 (2次)
比较 26 和 45 (3次)
比较 26 和 28 (4次)
比较 26 和 19 (5次)
最终插入位置在 19 和 28 之间: {7, 19, 26, 28, 45, 83, 92}
因此,正确查找次数为 5 次。
编程题
现在小明有一个长度为n的数组a,编号为0到n-1,其中初始条件下a[i]=i,
现在可以进行若干次操作,每一次操作对所有元素进行一次修改:对于编号为i的元素,若i是偶数,则a[i]= a[i/2],若i是奇数,则a[i]= a[n/2+(i-1)/2],现在小明想知道最少操作多少次(不可以不操作),能使得操作后的数组变成原数组。
输入描述
每个测试文件均包含多组测试数据。
第一行输入一个整数T(1≤T≤10^3)代表数据组数,每组测试数据描述如下:
第一行输入一个整数n(2≤n≤10^5)(且保证是一个偶数),代表数组的长度。
输出描述
对于每一组测试数据,输出一个答案代表最少的操作次数。
题解
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取测试用例的数量
int T = scanner.nextInt();
while (T-- > 0) {
// 读取数组的长度
int n = scanner.nextInt();
// 初始化原始数组
int[] original = new int[n];
for (int i = 0; i < n; i++) {
// 初始化原始数组的值
original[i] = i;
}
// 复制原始数组到当前数组
int[] current = Arrays.copyOf(original, n);
int operations = 0;
while (true) {
// 操作次数加1
operations++;
int[] next = new int[n];
for (int i = 0; i < n; i++) {
// 根据索引的奇偶性更新下一个数组的值
if (i % 2 == 0) {
next[i] = current[i / 2];
} else {
next[i] = current[n / 2 + (i - 1) / 2];
}
}
// 更新当前数组为下一个数组
current = next;
// 如果当前数组与原始数组相等,则跳出循环
if (Arrays.equals(current, original)) {
break;
}
}
// 输出操作次数
System.out.println(operations);
}
scanner.close();
}
}