目录
选择题
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
编程题
1. 合唱团
2. 马戏团
选择题
1.
子网掩码是 255.255.255.0,前三个字节都是 1,则表示有 24 位网络号和子网号。又是 B 类 IP 地址,只有 16 位网络号,所有第三个字节是子网,所以子网号是 160。
A 类 IP 地址:0.0.0.0 ~ 127.255.255.255 主机号有 24 位
B 类 IP 地址:128.0.0.0 ~ 191.255.255.255 主机号有 16 位
C 类 IP 地址:192.0.0.0 ~ 223.255.255.255 主机号有 8 位
2.
通过 IP 地址找到 MAC 地址的协议是 ARP 协议。
通过 MAC 地址找到 IP 地址的协议是 RARP 协议。
ICMP 协议是网络状况探测协议(ping)。
IP 协议负责路由选择,地址管理,数据包过大时分片与组合。
3.
cookie 是浏览器存储数据的机制,session 是服务器存储数据的机制。
cookie 和 session 存储的都是键值对,通过 sessionId 能够找到 session。
cookie 中存有 sessionId,sessionId 是连接 cookie 和 session 的桥梁。
cookie 和 session 经常一起使用,但也不是必须一起使用的,session 和 cookie 可以单独使用。
4.
等待 2MSL 时间是因为,ACK 在网络传输过程中可能会丢包,而如果被动关闭连接方一直没接收到 ACK,就会触发超时重传,此时会重传 FIN 给主动方,一来一回花费的时间就是 2MSL,保证此次通信的所有数据都消失在网络中,避免重传的数据对新连接造成影响。
5.
本题的释放连接指的是发送 FIN 请求。
FIN 表示自己不再发送数据,不表示自己不能接收数据,对方发送数据过来,还是能接收的。
6.
TCP 协议是有连接,可靠,全双工,面向字节流的。
TCP 建立连接需要三次握手,关闭连接需要四次挥手。
TCP 使用滑动窗口进行流量控制。
滑动窗口基于窗口大小字段实现,是接收方用于告诉发送方最多继续发送多少数据,避免发送过多缓冲区溢出。
TIME_WAIT 是主动关闭方会进入的状态。
7.
tcpdump 用于网卡抓包, top 用于查看 cpu 资源使用率。
netstat 用于查看网络通信连接状态,ifconfig 用于查看网卡信息。
8.
192.168.48.10:11000000.10101000.00110000.00001010 C 类 IP,24 网络号,多了 1 位
子网掩码:11111111.11111111.11111111.10000000 有 25 位网络号 + 子网号
则说明子网号就是黄色部分,也就是 192.168.48.0。
192.168.48.0 有 7 位主机号, 2 ^ 7 = 128 个主机,范围是 192.168.48.0 ~ 192.168.48.127
除去网络号(全 0)和广播号(全 1),有效的范围就是 192.168.48.1 ~ 192.168.48.126
9.
255.255.255.252:11111111.11111111.11111111.11111100
有 2 位主机号,有 32 - 2 = 30 位网络号,172.16.100.00000101
网络地址就是 IP 地址前 30 位,172.16.100.4,主机号 IP 地址最后两位,也就是 1
10.
NAT 是网络地址转换技术,用于组建私网,给主机分配私网地址,对外通信时,转换为对外的公网地址进行通信,用于节省公网地址的使用。
虚拟机中的地址都是 DHCP 动态分配的,不需要手动设置。
NAT 只是地址转换技术,将数据流经网关的源端地址转换为对外地址,跟地址怎么分配没有关系。
NAT 实现方式:
① 静态:一个私网 IP 地址对应一个公网 IP 地址,一对一固定不变
② 动态:转换地址不确定,在多个地址中动态转换
③ 端口多路复用:也叫 NAPT,私网内的大量主机可以使用同一个对外地址的不同端口进行对外通信。
编程题
1. 合唱团
思路:
代码实现:
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNextInt()) { // 注意 while 处理多个 case
int n = in.nextInt();
int[] arr = new int[n];
for (int i = 0; i < arr.length; i++) {
arr[i] = in.nextInt();
}
int k = in.nextInt();
int d = in.nextInt();
print(arr, k, d, n);
}
}
public static void print(int[] arr, int k, int d, int n) {
// 用动态规划来做
// dpMax[i][j] 就是取 j 个学生,并且最后一个学生是 arr[i - 1] 的乘积最大值
// dpMin[i][j] 就是取 j 个学生,并且最后一个学生是 arr[i - 1] 的乘积最小值
long[][] maxValue = new long[n + 1][k + 1];
long[][] minValue = new long[n + 1][k + 1];
// 初始化,如果 j == 1,则 dp[i][1] = 1
for (int i = 1; i <= n; i++) {
maxValue[i][1] = arr[i - 1];
minValue[i][1] = arr[i - 1];
}
// 用来记录最终结果
long ans = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= k; j++) {
// i - d <= z <= i - 1
for (int z = (i - d > 0 ? i - d : 0); z <= i - 1; z++) {
// 最大值可能是 最大正数*正数 最小负数*负数,自己本身
maxValue[i][j] = Math.max(maxValue[z][j - 1] * arr[i - 1], maxValue[i][j]);
maxValue[i][j] = Math.max(maxValue[i][j], minValue[z][j - 1] * arr[i - 1]);
// 最小值可能是 最大正数*负数 最小正数*正数,自己本身
minValue[i][j] = Math.min(minValue[z][j - 1] * arr[i - 1], minValue[i][j]);
minValue[i][j] = Math.min(minValue[i][j], maxValue[z][j - 1] * arr[i - 1]);
}
if (j == k) {
ans = Math.max(maxValue[i][j], ans);
}
}
}
System.out.println(ans);
}
}
2. 马戏团
代码实现:
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
// 可以定义一个对象来存放员工的身高体重信息
class Person {
public int num;
public int height;
public int weight;
public Person(int num, int weight, int height) {
this.num = num;
this.height = height;
this.weight = weight;
}
}
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNextInt()) { // 注意 while 处理多个 case
int n = in.nextInt();
List<Person> list = new ArrayList<>();
// dp[i] 表示以数组 i 下标结尾的最长身高升序子序列长度
int[] dp = new int[n];
for (int i = 0; i < n; i++) {
int num = in.nextInt();
int weight = in.nextInt();
int height = in.nextInt();
Person p = new Person(num, weight, height);
list.add(p);
// 顺便初始化 dp[i]
dp[i] = 1;
}
// 排序 list 数组
Collections.sort(list, new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
if (p1.weight == p2.weight) {
// 体重相同,按身高逆序排序
return p2.height - p1.height;
} else {
// 体重不同,按体重升序排序
return p1.weight - p2.weight;
}
}
});
for (int i = 0; i < list.size(); i++) {
Person pi = list.get(i);
for (int j = i - 1; j >= 0; j--) {
Person pj = list.get(j);
if (pj.height <= pi.height) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
}
// 遍历 dp 数组,求出最大值后输出
int max = 1;
for (int i = 0; i < dp.length; i++) {
if (dp[i] > max) {
max = dp[i];
}
}
System.out.println(max);
}
}
}