问答题
题1:Linux tcpdump监听网卡 eth0,对方主机IP为10.1.1.180,tcp端口为 80 的数据,相应命令为?
提示: tcpdump -i eth0 -nn 'tcp and port 80 and host 10.1.1.180'
其中 i
表示监听指定的端口,-nn
表示:直接以 IP 及 port number 显示,而非主机名和服务器名称
题2:tcp 三次握手的过程,accept 发生在三次握手哪个阶段?
A: 第一次握手
B: 第二次握手
C: 第三次握手
D: 三次握手后
题3:随着IP 网络的发展,为了节省可分配的注册IP 地址,有一些地址被拿出来用于私有 IP 地址,以下不属于私有 IP 地址范围的是?
A: 10.6.207.84
B: 172.23.30.28
C: 172.32.50.80
D: 192.168.1.100
答案:C
属于 A 类的私有地址:
10.0.0.0 – 10.255.255.255
属于 B 类的私有地址:
172.16.0.0 – 172.31.255.255(记住是16-31)
属于 C 类的私有地址:
192.168.0.0 – 192.168.255.255
编程题
题1:左右最值最大差
给定一个长度为N(N>1)的整型数组A,可以将A划分成左右两个部分,左部分A[0…K],右部分A[K+1…N-1],K 可以取值的范围是[0,N-2]。求这么多划分方案中,左部分中的最大值减去右部分最大值的绝对值,最大是多少?
给定整数数组A和数组的大小n,请返回题目所求的答案
测试样例:
[2,7,3,1,1],5
返回:6
class MaxGap {
public:
int findMaxGap(vector<int> A, int n) {
vector<int>Max(n);
vector<int>Min(n);
Max[0] = A[0];
for(int i = 1;i<n;++i){
Max[i] = max(Max[i-1],A[i]);
}
Min[n-1] = A[n-1];
for(int i = n-2;i>=0;--i){
Min[i] = max(Min[i+1],A[i]);
}
int maxnum = 0;
for(int i = 0;i<n;++i){
maxnum = max(maxnum,abs(Max[i]-Min[i]));
}
return maxnum;
}
};
题2:数据库连接池
Web系统通常会频繁地访问数据库,如果每次访问都创建新连接,性能会很差。为了提高性能,架构师决定复用已经创建的连接。当收到请求,并且连接池中没有剩余可用的连接时,系统会创建一个新连接,当请求处理完成时该连接会被放入连接池中,供后续请求使用。现在提供你处理请求的日志,请你分析一下连接池最多需要创建多少个连接。
- 输入描述:输入包含多组数据,每组数据第一行包含一个正整n(1≤n≤1000),表示请求的数量。紧接着n行,每行包含一个请求编号id(A、B、C……、Z)和操作(connect或disconnect)。
- 输出描述:对应每一组数据,输出连接池最多需要创建多少个连接。
输入
6
A connect
A disconnect
B connect
C connect
B disconnect
C disconnect
输出
2
#include <iostream>
#include <fstream>
#include <algorithm>
#include <string>
#include <set>
using namespace std;
int main(){
int n;
while (cin >> n){
set<string> pool;
string id, con;
int maxSize = 0;
for (int i = 0; i < n; ++i){
cin >> id >> con;
if (con == "connect") {
pool.insert(id);
}else if (con == "disconnect"){
pool.erase(id);
}
int size = pool.size();
maxSize = max(maxSize, size);
}
cout << maxSize << endl;
}
return 0;
}
#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
int main() {
int n;
char id;
string str;
while (cin >> n) {
int sum = 0;
int max = 0;
for (int i = 0; i < n; ++i) {
cin >> id >> str;
if (str == "connect") {
sum++;
if (sum > max) {
max = sum;
}
}
else if (str == "disconnect") {
--sum;
}
}
cout << max << endl;
}
system("pause");
return 0;
}
题3: mkdir
工作中,每当要部署一台新机器的时候,就意味着有一堆目录需要创建。例如要创建目录“/usr/local/bin”,就需要此次创建“/usr”、“/usr/local”以及“/usr/local/bin”。好在,Linux下mkdir提供了强大的“-p”选项,只要一条命令“mkdir -p /usr/local/bin”就能自动创建需要的上级目录。现在给你一些需要创建的文件夹目录,请你帮忙生成相应的“mkdir -p”命令。
-
输入描述:输入包含多组数据。每组数据第一行为一个正整数 n (1≤n≤1024)。紧接着 n 行,每行包含一个待创建的目录名,目录名仅由数字和字母组成,长度不超过 200 个字符。
-
输出描述:对应每一组数据,输出相应的、按照字典顺序排序的 “mkdir -p” 命令。每组数据之后输出一个空行作为分隔。
输入
3
/a
/a/b
/a/b/c
3
/usr/local/bin
/usr/bin
/usr/local/share/bin
输出
mkdir -p /a/b/c
mkdir -p /usr/bin
mkdir -p /usr/local/bin
mkdir -p /usr/local/share/bin
解题思路:如何去判断在什么时候应该递归创建,什么时候不应该递归创建?
而且该题还有一个问题就是:结果必须是按照字典序已经排好序的,这一点可以在输入的时候利用 sort 函数进行排序,然后再判断。
-
如果两个字符串是相同的则是重复创建
-
如果前一个是后一个的字串,且后一位还有一个 ‘/'字符,则已经说明这是应该要递归创建的
#include <iostream>
#include <fstream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
int main(){
int n;
while (cin >> n){
vector<string> list(n);
vector<bool> flag(n, true);
for (int i = 0; i < n; ++i) {
cin >> list[i];
}
sort(list.begin(), list.end());
//将类似字符串经过排序,放在一起
for (int i = 0; i < list.size() - 1; ++i){
// 1、两串相同
// 2、前串是后串的子串,而且后串后一位是 '/'
if (list[i] == list[i + 1]) {
flag[i] = false;
}
else if (list[i].size() < list[i + 1].size()
&& list[i] == list[i + 1].substr(0, list[i].size())
&& list[i + 1][list[i].size()] == '/')
{
flag[i] = false;
}
}
for (int i = 0; i < list.size(); ++i) {
if (flag[i]) {
cout << "mkdir -p " << list[i] << endl;
}
}
cout << endl;
}
return 0;
}
题4:顺时针打印矩阵
对于一个矩阵,请设计一个算法从左上角(mat[0][0])开始,顺时针打印矩阵元素。给定 int 矩阵 mat , 以及它的维数 nxm,请返回一个数组,数组中的元素为矩阵元素的顺时针输出
测试样例:
[[1,2],[3,4]],2,2
返回:[1,2,4,3]
方法一:一个矩形可以由左上角和右下角坐标定义,每次循环都要重新定位,在处理边界的时候会比较麻烦点
class Printer {
public:
vector<int> clockwisePrint(vector<vector<int> > mat, int n, int m) {
int x1 = 0,y1 = 0;
int x2 = n-1,y2 = m-1;
vector<int>v;
while(x1<=x2 && y1<=y2){
// 最上行的所有数据
for(int i = y1;i<=y2;++i){
v.push_back(mat[x1][i]);
}
// 最右行从 x1 + 1 开始,x2-1结束
for(int i = x1+1;i<x2;++i){
v.push_back(mat[i][y2]);
}
// 最下行的所有数据
for(int i = y2;x2>x1 && i>=y1;--i){
v.push_back(mat[x2][i]);
}
// 最左行从 x2-1 开始,x1+1 结束
for(int i = x2-1;y2 > y1 && i > x1;--i){
v.push_back(mat[i][y1]);
}
x1++;
y1++;
x2--;
y2--;
}
return v;
}
};
方法二:利用一个方向数组,当容器的值等于 m * n 时,返回容器数组
class Printer {
public:
vector<int> clockwisePrint(vector<vector<int> > mat, int n, int m) {
// 定义方向数组
int dict[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
vector<int>res;
int i = 0,start = 0;
int j = -1;
while(1){
int a = i + dict[start][0];
int b = j + dict[start][1];
if (!(0 <= a && a < n) ||
!(0 <= b && b < m) ||
mat[a][b] == INT_MAX) {
start = (start + 1) % 4;
}
i += dict[start][0];
j += dict[start][1];
res.push_back(mat[i][j]);
// 设置标记
mat[i][j] = INT_MAX;
if(res.size()== m*n){
break;
}
}
return res;
}
};