1.linux系统 load average 返回的三个值,哪一个作为系统长期负载高的参考值比较准确?()
A.第一个;B .第二个;C .第三个
答案:C
解析:
load average 定义:linux系统中的Load是对当前CPU工作量的度量。简单的说是进程队列的长度。
Load Average 就是一段时间 (1 分钟、5分钟、15分钟) 内的平均 Load 。
如果系统cpu超负荷 load average会大于您机器的cpu数量
三种Load值,应该看哪个,通常我们先看15分钟load,如果load很高,再看1分钟和5分钟负载,查看是否有下降趋势。 1分钟负载值 > 1,那么我们不用担心,但是如果15分钟负载都超过1,我们要赶紧看看发生了什么事情。所以我们要根据实际情况查看这三个值。
2.mysql explain返回结果的type列字段,下面哪种类型表示的查询效率最高?()
A.index;B.system;C.const;D.range
答案:B
解析:
type:显示了连接使用了哪种类别,有无使用索引,是使用Explain命令分析性能瓶颈的关键项之一。
结果值从好到坏依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
一般来说,得保证查询至少达到range级别,最好能达到ref,否则就可能会出现性能问题。
3.char str[] = “Hello”; char *p = str; sizeof(p) = ?
A.1;B.5;C.6;D.8
答案:D
解析:
sizeof:是运算符,获取某个数据类型所占用空间的字节数,参数可以是数组、指针、类型、对象、函数等。
strlen:是函数,参数必须是字符型指针,返回字符串的长度。从代表该字符串的第一个地址开始遍历,直到遇到结束符NULL。返回的长度大小不包括NULL(字符串以“\0”结尾,但是不计入长度)
指针的长度和机器有关,64位机对应8个字节,32位机对应4个字节。
4.一个 C 程序运行时,对于内存中堆栈的描述,哪些是正确的?()
A.堆用来保存函数的局部变量
B.栈用来保存函数的局部变量
C.堆的内存由程序员直接控制
D.栈的内存由程序员直接控制
答案:B、C
解析:
数据段 :数据段(data segment)通常是指用来存放程序中 已初始化 的 全局变量 的一块内存区域。数据段属于静态内存分配。
代码段: 代码段(code segment/text segment)通常是指用来存放 程序执行代码 的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于 只读 , 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些 只读的常数变量 ,例如字符串常量等。程序段为程序代码在内存中的映射.一个程序可以在内存中多有个副本.
堆(heap) :堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc/free等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张)/释放的内存从堆中被剔除(堆被缩减)
栈(stack) :栈又称堆栈, 存放程序的 局部变量 (但不包括static声明的变量, static 意味着 在数据段中 存放变量)。除此以外,在函数被调用时,栈用来传递参数和返回值。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。储动态内存分配,需要程序员手工分配,手工释放
![](/qrcode.jpg)
5.下面关于 TCP 协议网络端口的描述,哪些是正确的?()
A.端口号范围大小受限于操作系统的内存
B.端口号范围没有限制
C.端口号范围大小受限于操作系统的文件句柄数量
D.网络端口号范围大小受限于TCP 协议
答案:D
6.顺序表的”假溢出”是什么?循环队列怎么推断是空还是满?请给出判断公式 ?
顺序队列中,如果没有按照取余数的方式入队,就会在数组的最后,出现数组溢出,这时候,即使数组前面有空间,也不能正确入队,形成假溢出。
数组队尾元素已经占用。而队首地方还是空暇的,解决假溢出的办法就是后面满了就再从头開始,也就是头尾相接的循环
假设队列最大长度为QueueSize。那么队列满的条件是(rear+1)%QueueSize==front.
通用的计算队列长度的公式为:(rear-front+QueueSize)%QueueSize
7.什么是进程(Process)?什么是线程(Thread)?有何区别?
进程:
进程是程序执行的的一个实例
每个进程拥有独立内存地址空间
是系统进行资源分配和调度的基本单位
线程:
线程是进程的一个实体,是进程的一个执行路径
CPU调度和分派的基本单位
线程本身不会独立存在
系统不会为线程分配内存,多个线程之间共享所属进程的资源
线程只拥有在运行中必不可少的资源(如程序计数器,栈等)
为什么要有线程?因为每个进程都有自己的地址空间,即进程空间,在并发请求中,如果为每一个请求创建一个进程,系统开销很大,请求响应效率低,因此引进了线程
一个程序至少一个进程,一个进程至少一个线程,进程中多个线程共享进程的资源
进程通信是通过管道,信号量,套接字,消息队列文件等来通信的
8.分别描述TCP的3次握手和四次挥手的定义、目的和过程?
三次握手过程是:
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。完成三次握手,客户端与服务器开始传送数据.
为什么要三次握手?
第一次握手:客户端发送网络包,服务端收到了。这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。
第二次握手:服务端发包,客户端收到了。这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。
第三次握手:客户端发包,服务端收到了。这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。所以三次握手就能确认双发收发功能都正常,缺一不可
四次挥手
第一次挥手:A数据传输完毕需要断开连接,A的应用进程向其TCP发出连接释放报文段(FIN = 1,序号seq = u),并停止再发送数据,主动关闭TCP连接,进入FIN-WAIT-1状态,等待B的确认。
第二次挥手:B收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),B进入CLOSE-WAIT关闭等待状态,此时的TCP处于半关闭状态,A到B的连接释放。而A收到B的确认后,进入FIN-WAIT-2状态,等待B发出的连接释放报文段。
第三次挥手:当B数据传输完毕后,B发出连接释放报文段(FIN = 1,ACK = 1,序号seq = w,确认号ack=u+1),B进入LAST-ACK(最后确认)状态,等待A 的最后确认。
第四次挥手:A收到B的连接释放报文段后,对此发出确认报文段(ACK = 1,seq=u+1,ack=w+1),A进入TIME-WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,A才进入CLOSE状态。
关闭连接时,被动关闭方可能还需要发送一些数据后,再发送FIN报文表示同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的,所以需要四次挥手。
9.什么是覆盖索引?优点有哪些?举个适用的场景(包括表结构和查询语句)。
覆盖索引指一个查询语句的执行只需要从辅助索引中就可以得到查询记录,而不需要查询聚集索引中的记录。
优点:只需要通过索引就可以返回查询所需要的数据,而不必在查到索引之后进行回表操作,减少IO操作,提高了效率。
10.如何判断一个整数是2的整数次幂?
两种解法:
一是暴力解法,不断对数%2,如果不为0,就/2(除以2)循环直到为0
二是将数减1,与原数进行与操作,如果为0则是,否则不是
11.什么是用户态和内核态?从什么方面区分这两个?用户态切内核态有哪些情况?
当一个进程在执行用户自己的代码时处于用户运行态(用户态),此时特权级最低,为3级,是普通的用户进程运行的特权级,大部分用户直接面对的程序都是运行在用户态。Ring3状态不能访问Ring0的地址空间,包括代码和数据;当一个进程因为系统调用陷入内核代码中执行时处于内核运行态(内核态),此时特权级最高,为0级。执行的内核代码会使用当前进程的内核栈,每个进程都有自己的内核栈。
当在系统中执行一个程序时,大部分时间是运行在用户态下的,在其需要操作系统帮助完成一些用户态自己没有特权和能力完成的操作时就会切换到内核态。
用户态切换到内核态的3种方式:
(1)系统调用
(2)异常
(3)外围设备的中断
12.编程题
把m个同样的足球放进n个同样的篮子里,允许有的篮子为空,问共有几种分法?
例如:3, 2, 1和2, 1, 3是同一种分法。
n,m(1<=n<=70,1<=m<=70)用空格隔开,表示篮子数和足球数。
输入例子1:
3 7
输出例子1:
8
public static int helper(int n, int m, int init){
int res = 0;
// 如果球数小于初始化的球数,则为0
if (m < init){
return res;
}
// 篮子为一个,则只能放在一起,也就为1
if (n == 1){
res = 1;
} else {
for (int i = init; i <= m - init; i++){
res += helper(n-1, m - i, i);
}
}
return res;
}
public static void main(String []args){
Scanner sc = new Scanner(System.in);
while (sc.hasNext()){
int n = sc.nextInt();
int m = sc.nextInt();
System.out.println(helper(n,m,0));
}
}
一台新机器,第4年可以生产一台机器,以后每一年生产1台。 生产出来的新机器第4年又可以生产一台机器,后续每年可以生产1台。
现在有一台新机器,求第n年总共有多少台机器。 计算结果对109+7取模。
输入描述:
输入一个数字 n,表示计算第 n 年总共有多少台机器。(1<=n<=106)
输出描述:
输出第 n 年总共的机器的台数 X 对109+7取模之后的结果。
输入例子1:
10
输出例子1:
19
/*
设第k年生产的机器生日为k, 当前年份为n;
则: 当n - 3 > k时, 产生新机器。
那么,只要我们知道所有年龄大于3的机器数量,也就知道了今年新机器的数量
即 numOfThisYear = num[1] + num[2] + .... + num[n - 3];
*/
public static int product(int x){
if (x < 4){
return 1;
}
int []dp = new int[x];
dp[0] = dp[1] = dp[2] = 1;
for (int i = 3; i < x; i++){
dp[i] = (dp[i-1] + dp[i-3]) % 1000000007;
}
return dp[x-1] ;
}
public static void main(String []args){
Scanner sc = new Scanner(System.in);
System.out.println(product(sc.nextInt()));
}
给一个01矩阵,1代表是陆地,0代表海洋, 如果两个1相邻,那么这两个1属于同一个岛。我们只考虑上下左右为相邻。
岛屿: 相邻陆地可以组成一个岛屿(相邻:上下左右) 判断岛屿个数。
/*
思路:遍历,然后进行标记,并为了防止重复进入同一区域,进行赋值0操作,然后dfs上下左右
*/
public static int getIslandNum(char [][]island){
int m = island.length, n = island[0].length;
int res = 0;
for (int i = 0; i < m; i++){
for (int j = 0; j < n; j++){
if (island[i][j] == '1'){
res++;
helper(island,i,j);
}
}
}
return res;
}
public static void helper(char [][]island, int i, int j){
island[i][j] = '0';
if (i - 1 >= 0 && island[i-1][j] == '1'){
helper(island,i-1,j);
}
if (j - 1 >= 0 && island[i][j-1] == '1'){
helper(island,i,j-1);
}
if (i + 1 < island.length && island[i+1][j] == '1'){
helper(island,i+1,j);
}
if (j + 1 < island[0].length&& island[i][j+1] == '1'){
helper(island,i,j+1);
}
}
public static void main(String []args){
Scanner sc = new Scanner(System.in);
String []s = sc.nextLine().split(" ");
int m = Integer.parseInt(s[0]), n = Integer.parseInt(s[1]);
char [][]island = new char[m][n];
for (int i = 0; i < m; i++){
island[i] = sc.nextLine().toCharArray();
}
System.out.println(getIslandNum(island));
/*
for (char []nums : island){
for (int val: nums){
System.out.print(val + " ");
}
System.out.println();
}*/
}