刚刚亲身体验的2017企业笔试题集第一篇,本人感觉,有新手级别的问题、也有较为复杂的问题,这里先将笔试问题和部分答案总结放出,感兴趣的朋友可以mark一下,有新答案时本文章将更新~~
2017腾讯模拟笔试--移动端开发
-
()是一个独立可交付的功能单元,外界通过接口访问其提供的服务?
答:基于构件开发中的构件(Component)
个人理解:相比于以上的构件,- 面向对象系统中的对象(Object):重点是“面向对象系统”,强调对象属性和功能,对于'独立可交付'的概念,这里并没有看出对象有此能力。
- 模块化程序设计中的子程序(Subroutine):“模块化”,我们都知道,一个项目有多个业务,每个业务有不少功能模块,而单个模块子程序不太可能“独立交互”吧,当然得整个项目雏形出来了,才可谈交付。
- 系统模型中的包(Package):“包”强调按“功能”或“属性和类型”对基本组件进行划分,和“独立可交互”并没有太大关系。
-
设计模式和对应例子
答:Android相关的26种设计模式 -
动态库和静态库的优劣
解析: - 使用动态库,可以将最终可执行文件体积缩小
- 使用动态库,多个应用程序共享内存中得同一份库文件,节省资源
- 使用动态库,可以不重新编译连接可执行程序的前提下,更新动态库文件达到更新应用程序的目的。
库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。库分静态库和动态库两种。
- 静态函数库
这类库,Linux中的名字一般是libxxx.a,Window中是xxx.lib;利用静态函数库编译成的文件比较大,因为整个 函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。 - 动态函数库
这类库,Linux中的名字一般是libxxx.so,Window中是xxx.dll;相对于静态函数库,动态函数库在编译的时候 并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。
详细可看:
C/C++的const、virtual关键字,& 和 指针相关
简单分析:coust关键字:可以看成Java的final关键字,被修饰的对象,只能在初始化时被赋值一次,被当成是常量。
virtual关键字:可以比作Java的abstract关键字,用于修饰方法的话,父类的该方法可以由子类来重写。
&和指针,不多说。
Http 响应状态码
可以参考百度百科,查看细节(HTTP状态码)100-199 用于指定客户端应相应的某些动作。1XX表示:消息
200-299 用于表示请求成功。2XX表示:成功
300-399 用于已经移动的文件并且常被包含在定位头信息中指定新的地址信息。3XX表示:重定向
400-499 用于指出客户端错误。4XX表示:客户端错误
-
500-599 用于支持服务器错误。5XX表示:服务端错误
栈溢出攻击
解析:详细可以参考这篇简书,可以理解为:利用内存中存储的数组等连续且有限的存储地址上,存储大于这个连续长度的数据,导致内存的这一连续存储区域不够装载数据,从而把溢出的数据存储到相邻的存储单元中,导致相邻的数据改变,的这种攻击。判断:NDK更容易获取更多的Android系统层的API?
答:这里,是错误的。因为NDK只是一套工具的集合,在新的SDK中被集成,目的只是辅助Android JNI更好、更快捷地开发native方法等,可以吧NDK看做是Android JNI相关语法操作的部分封装,它最终还是会调用Android JNI相关操作,Android系统层的API赋予访问的权限没变。针对手Q/微信,哪三个性能指标对手机的耗电影响大?
矩阵乘法
完全二叉树的结点问题
解析:这里提一提几个公式,详情可以看看我的文章《程序员面试闯关(二):数据结构考点与细节分析》
- 在二叉树的第i层上至多有2^(i-1)个结点
- 深度为k的二叉树至多有2^k -1个结点
- 任意一颗二叉树,n2(度数为2的结点) = n0(度数为0的结点)-1
- 树的边数(也叫:分支线总数)和结点数的关系:边数 = n-1 = n1+2*n2(其中n1表示度为1的结点,n2表示度为2的结点)
- IOS下,开启ARC内存管理的代码
-
操作系统:用户态和内核态
解析:
用户态和内核态(详细可以参考下这篇文章)- 定义:我们所面对的基本所有应用程序都是用户进程、处于用户态,而内核态是相对于内核态而言的,用户态的程序对于数据访问区域等都会被限制,无法访问一些系统重要数据和系统操作,而需要拥有访问这些‘特权级别数据’的能力的进程才能访问和处理,比如系统进程。那么就有了内核态,系统进程就处于内核态。总的来说:
内核态: CPU可以访问内存所有数据, 包括外围设备, 例如硬盘, 网卡. CPU也可以将自己从一个程序切换到另一个程序。
**用户态: **只能受限的访问内存, 且不允许访问外围设备. 占用CPU的能力被剥夺, CPU资源可以被其他程序获取。 - 用户态切换到内核态的方式:
系统调用:用户进程有需要用到如读取系统键盘输入或者从硬盘读取数据等只有系统进程有权利做得事情,那么,就需要以程序本身的名义去请求系统,让系统根据程序的意愿去访问这些操作,用户态程序切换到内核态, 但是不能控制在内核态中执行的指令,这就是系统调用。
总体的过程是:用户态程序将一些数据值放在寄存器中, 或者使用参数创建一个堆栈(stack frame), 以此表明需要操作系统提供的服务.
用户态程序执行陷阱指令(陷阱指令是CPU实现系统调用的具体方式)
CPU切换到内核态, 并跳到位于内存指定位置的指令, 这些指令是操作系统的一部分, 他们具有内存保护, 不可被用户态程序访问
这些指令称之为陷阱(trap)或者系统调用处理器(system call handler). 他们会读取程序放入内存的数据参数, 并执行程序请求的服务系统调用完成后, 操作系统会重置CPU为用户态并返回系统调用的结果
异常:当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。
外围设备的中断:当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。
- 定义:我们所面对的基本所有应用程序都是用户进程、处于用户态,而内核态是相对于内核态而言的,用户态的程序对于数据访问区域等都会被限制,无法访问一些系统重要数据和系统操作,而需要拥有访问这些‘特权级别数据’的能力的进程才能访问和处理,比如系统进程。那么就有了内核态,系统进程就处于内核态。总的来说:
-
死锁和银行家算法
解析: - 死锁:所谓死锁,是指两个以上的进程互相都要求对方已经占有的资源导致无法继续运行下去的现象。
-
死锁产生的必要条件:
(1)互斥:即一个资源每次只能被一个进程使用,在操作系统中这是真实存在的情况。
(2)占有且等待:有一个进程已获得了一些资源,但因请求其他资源被阻塞时,对已获得的资源保持不放。
(3)占有资源不可剥夺:有些系统资源是不可剥夺的,当某个进程已获得这种资源后,系统不能强行收回,只能由进程使用完时自己释放。
(4)环路等待:若干个进程形成环形链,每个都占用对方要申请的下一个资源。 -
死锁预防:死锁预防是采用某种策略,限制并发进程对资源的请求,破坏死锁产生的4个必要条件之一,使系统在任何时刻都不满足死锁的必要条件。
(1)预先静态分配法。破坏了“不可剥夺条件”。预先分配所需资源,保证不等待资源。该方法的问题是降低了对资源的请求,降低进程的并发程度;有时可能无法预先知道所需资源。
(2)资源有序分配法。破坏了“环路条件”。把资源分类按顺序。保证不形成环路。该方法存在的问题是限制进程对资源的请求;由于资源的排序占用系统开销。 - 死锁避免:避免是指进程在每次申请资源时判断这些操作是否安全,典型算法是“银行家算法”。但这种算法会增加系统的开销。
- 死锁检测:判断系统是否处于死锁状态,如果是,则执行死锁解除策略。
- 死锁解除:与死锁检测结合使用,它使用的方式就是剥夺。即将资源强行分配给别的进程。
- 关于银行家算法,可以参考这里。
- 问答题:王者荣耀游戏中,如下两个问题该如何考虑:实时PVP同步问题 和 技术选型
京东(练习题)
Redhat 9 支持的安装方式:
A.Telnet网络安装
B.HTTP网络安装
C.本地硬盘驱动器进行安装
D.通过NFS进行网络安装
答案:BCDPHP相关
<bean:define xxxx>
<bean:write>
- 等等
- Linux基本命令
- C/C++基础编程问题,如下
int main()
{
int n[][3] = {1,2,3,4,5,6};
int (*p)[3];
p = n;
printf("%d %d %d\n", p[0][0], *(p[0]+1), (*p)[2]);
return 0;
}
输出为:1,2,3
-
编程题:水仙花数
解析:
水仙花数是指一个 n 位数 ( n≥3 ),它的每个位上的数字的 n 次幂之和等于它本身。较简单,示例解法如下:
///获取100到999之间的水仙花数的总数
public class ShuiXianHuaShu {
public static void main(String[] args) {
int x = 0; //定义水仙花数的个数
for(int i=100;i<=999;i++){
int b = i/100; //取得百位数
int s = i%100/10; //取得十位数
int g = i%10; //取得个位数
if(i==Math.pow(b, 3) + Math.pow(s, 3) + Math.pow(g, 3)){
x++; //每次符合水仙花数条件,则x+1;
System.out.print(i+" "); //输出符合条件的数
}
}
System.out.println(); //换行
System.out.println("水仙花数总共有"+x+"个"); //输出水仙花数的总数
}
}
```
-
Java 求N次方、开N次方根、求绝对值相关函数:
答:Math.pow(N) , Math.sqrt(N), Math.abs(N)
京东2017笔试
- 排序的分类(基于比较的排序?)
- 计数排序
- 正则表达式:问:只能输入0 或者 非零开头的数字
- 获取手机屏幕的方法:getMetrics() ?
-
计网:属于DHCP客户端的消息有?
offer,request,ack ,还有吗? - 软件工程:数据流图 加工
- MySQL的Hash索引
- 补码 加减法
- 关于 RISC的特征
-
二叉排序树 与 二分查找
解释:具体题目考的是二叉排序树下给定元素,并进行查找该元素的所用步数最多最少问题,可以看成二分查找问题。 - 什么是 活前缀
- 线性窥孔优化的特点
<input>
的type属性- SNMP (简单网络管理协议)
- 计算机网络安全的目标?
- apache目录访问控制的参数有哪些?
- 点9图片的特点和用法
- gc的基本原理和主动请求gc的方法
- activity退出的方法?如何退出多个Activity?
2017阿里笔试
-
OS:双核CPU性能要提升1/4,那么,每一条指令的执行速率需要提升多少?
答:个人感觉这里考察CPU性能指标。可以参考CPU性能指标
这道题没有说系统是否支持CPU并发处理的能力,如果支持、并且指令平分在几个可并发执行的程序中,那么,一条指令执行速率只需要提升1/8,否则,需要提升1/4。 - 几何:相同周长的圆内四边形和三角形,哪个面积更大?(类似问题)
-
概率论:概率问题
答:这里主要是计算公式的记忆。 - OOM的情形和解决方案
- Android客户端,用Java实现一个线程池(可用Java数据结构),需满足:(需要看看线程池的实现原理)
- 可往前/往后插入task
- 可配置最大同时执行线程数
- 对线程池中当前同一个类型的连续task进行合并执行。
- 编程题:输入一个只有大小写字母和数字的字符串,最终,输入所有数字中出现次数最多的那个数字的总和。如:输入
ab11c2d3ff11ee
,则输出22
2017腾讯笔试
一、选择题
- IOS常用的多线程编程组件:GCD?NSOperationQueue?NSThread?
-
C/C++ “virtual”
答:被修饰的对象可被子类重写,类似于Java的abstract关键字。 -
大字节序和小字节序相关问题
解析:
端模式分为:小端字节序和大端字节序,也就是字节在内存中的顺序。【内存低地址指的是:地址下标较小的地址】
- 小端字节序:低字节存于内存低地址;高字节存于内存高地址。
-
大端字节序:高字节存于内存低地址;低字节存于内存高地址。
例子如下:
内存地址 大端字节序 小端字节序
0x0000ff08 0x12 0x78
0x0000ff09 0x34 0x56
0x0000ff0a 0x56 0x34
0x0000ff0b 0x78 0x12
- 关于死锁:
- 有序分配资源可以预防死锁?
- 银行家算法可以检测死锁?
- 剥夺所有资源,可以解除死锁?
-
TCP能力:
- 端到端流量控制?
- 数据按需到达?
- Linux进程间通信
- 广播属于Android跨进程通信
- QQ、FTP、HTTP、DNS,哪些只用了TCP,没有用UDP?
- C/C++,关于:
-
~A()
是什么意思? -
delete
和delete[]
是什么?
- C语言的
sizeof()
问题:
int a = 1024;
char[] ch = "abc";
const char* p = ch;
///然后,求sizeof(a) , sizeof(ch), sizeof(p)
答: 代码的结果是:4 4 4
解析:a是int类型,4byte;ch是字符数组,使用sizeof(ch)会算上字符数组末尾隐含的\0
结束符,所以,一共有3+1个char,4byte;p是指针,指向字符数组,p指向的是数组,数组是引用类型,所以其实ch和p的作用一样,所以ch的大小就是p的大小。
-
Android九宫格解锁(4<=点数<=9)有多少种路径? 389112种?
答: 389112种,详细解法可看这里 - 数据库:唯一约束和主键的关系
- 数据库:复合索引
- ARP协议
- 数据库:
count()
语句用法 -
*p=Struct XXX{}
,那么,p的地址,是结构体的哪个位置?*
答:指向结构体的第一个元素的首地址
如下例子:#include <stdio.h> #include <stdlib.h>
typedef struct {
int a;
int b;
char c;
}Node , *NodePtr;
int main()
{
Node node;
node.a = 2;
node.b = 3;
node.c = 'C';
NodePtr q = &node;
printf("%d %d %d %d",q,&(q->a), &(q->b), node.b);///q 和 &(q->a)的值一样,是node.a的地址,&(q->b) = &(q->a)+4
return 0;
}
```
-
数据库范式相关:关系模式R中,属性全是主属性,则R最高范式是?
答:第三范式
解析:- 这样如R(X,Y,Z), F={Y--Z, XZ--Y}. XY和XZ都可以做为候选码,即R中的属性全为主属性,且不存在非主属性对码的传递函数依赖,因此R属于3NF.
BCNF的定义是:关系模式R<U,F属于1NF.若Y函数依赖于X且Y不包含于X时X必含有码,则R<U,F属于BCNF.即若每一个决定因素都包含码,则R属于BCNF.
BCNF中有一条性质,是所有的主属性对每一个不包含它的码,是完全函数依赖.这样当选择XY做为主码时,Z就对XY部分函数依赖了(因为Z函数依赖于Y,也就是Z函数依赖于主码XY的一部分,而不是XY整体),因此R不属于BCNF。
- 这样如R(X,Y,Z), F={Y--Z, XZ--Y}. XY和XZ都可以做为候选码,即R中的属性全为主属性,且不存在非主属性对码的传递函数依赖,因此R属于3NF.
扩展:关于范式
* 第一范式【如果关系R中所有属性的值域都是单纯域,那么关系模式R是第一范式。】
* 有主键
* 主键不为空
* 主键不能重复
* 字段不可再分
* 第二范式【如果关系模式R是第一范式的,而且关系中每一个非主属性不部分依赖于主键,称R是第二范式的。】
* 是1NF
* 非主属性完全依赖于码。
* 第三范式【符合2NF,并且,消除传递依赖,即要求一个数据库表中不包含已在其它表中已包含的非主关键字信息】
* 是2NF
* 不存在依赖传递,比如:表一中有A和B两属性,表二有B和C两属性,那么如果满足A ->B ,B ->C,那么,就不满足3NF,因为依赖关系被传递了。
-
C++上的空类,在32位机器上,sizeof占多大?
答案:1
解析:- 实例化的原因(空类同样可以被实例化),每个实例在内存中都有一个独一无二的地址,为了达到这个目的,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存得到了独一无二的地址,所以空类所占的内存大小是1个字节。
- 扩展:C和C++编译器有所不同:
表示:C++编译器默认分配一个字节(如果内部没有成员,有,则以成员总空间为主),以便标记可能初始化的类的实例,同时使空类占用的空间也最少(即1字节)。而C编译器,则给空struct分配0字节的空间。struct node{ }; class A{ }; class B : public A{ private: int b; }; class C : public A{ }; class D : public B{ }; class ClassE { public: int GetReturnValue() { return 0; } }; int main(){ cout << "A " << sizeof(A) << endl; //C++: 1 cout << "B " << sizeof(B) << endl; //C++: 4 cout << "C " << sizeof(C) << endl; //C++: 1 cout << "D " << sizeof(D) << endl; //C++: 4 cout << "E " << sizeof(ClassE) << endl; //C++: 1 cout << "node " << sizeof(node) << endl; //C++: 1 C:0 }
为什么C++要至少分一个字节给类和结构体呢?C++标准中规定,“no object shall have the same address in memory as any other variable” ,就是任何不同的对象不能拥有相同的内存地址。 如果空类大小为0,若我们声明一个这个类的对象数组,那么数组中的每个对象都拥有了相同的地址,这显然是违背标准的。
公司局域网上ping www.qq.com 没有涉及到的网络协议:TCP ? DNS ? ICMP ? ARP ?
答案:全都涉及到。
解析:
- 首先, Ping的含义是:校验与远程计算机或本地计算机的连接。只有在安装 TCP/IP 协议之后才能使用该命令。则ping操作涉及到TCP。
- 注意ping 的是一个http网址,它最终需要经过DNS转换为IP地址,也就是最终ping校验的是相应的IP地址,所以,这个过程也涉及到DNS。
- Ping 命令通过向计算机发送 ICMP 回应报文并且监听回应报文的返回,以校验与远程计算机或本地计算机的连接,这个ping的过程实际上就是ICMP协议工作的过程。说明,而涉及到ICMP。
- ARP协议是“Address Resolution Protocol”(地址解析协议)的缩写。它用于将IP地址转换为mac地址【计算机物理地址】。如果主机A要Ping主机B,那么主机A就要封装二层报文,他会先检查自己的MAC地址,如果没有B的MAC地址,就会向外发送一个ARP广播包。说明,ping过程也会涉及到ARP协议。
相关参考:
* ping的整个过程
* ARP和ping的区别
-
C语言:
#pragma.pack(2)
代表什么?
解析:每个特定平台上的编译器都有自己的默认“对齐函数”(也称为对齐模数)#grama.pack(n)
其中n可表示你的“对齐系数”,可取:1(boolean、char的大小)、2(short的大小)、4(int的大小)、8(float,long的大小)、16(double的大小)
规则: - 数据成员的对齐规则:结构(struct)(或者联合(union))的数据成员,第一个数成员放在offset为0的地方,以后的每个数据成员的对齐按照
#pragma.pack(n)
中的“n”指定的数值和数据成员自身长度中,比较小的那个来进行。 - 结构/联合的整体对齐规则:在数据成员完成各自对齐之后,结构(联合)本身而要进行对齐,对齐将按照
#gragma.pack(n)
指定的数值和结构(联合)最大数据成员长度中,比较小的那个进行。
例子:
#pragma pack(4)
struct test {
char m1;//1 -> 4
double m4; //16 ->16
int m3; // 4 ->4
}
#pragma pack()
struct test t;
printf(sizeof(t));///输出是24
#pragma pack(8)
typedef struct {
char i;//1
char j;//1
}s1;
typedef struct {
short i;//2
s1 k;// 2+1的占用空间
char j;//1
}s2;
#pragma pack()
sizeof(s1) = 2;sizeof(s2) = 6;他们都不是按照8个字节对齐的。
二、问答题
- 设计一个“抢红包”业务,如现在我有200个钻石,我把他们分成20份,让10万粉丝来抢,问:
- 如何设计钻石分配算法?
- 红包分数有限,高并发下怎么解决 固定分数和 限额问题?
- 如果高峰阶段,抢红包的并发请求数可能达到8000次/秒,怎样的存储系统可支持该方案?
- 编程题:a~y 25个字母,用索引表示字母序列,如:a = 1, aa = 2 , aaa = 3, aaaa = 4 ,aaab = 5 …… ,一共有 a 到 yyyy 这么多种字母串,问:设计一个函数, 输入一个字母串,如‘abcd’ ,输出这个字母串对应的索引值?