首页 > 代码库 > 搜狗2015C++工程师笔试题解题分析
搜狗2015C++工程师笔试题解题分析
试卷链接:搜狗2015 C++工程师笔试题。
1、假设整数0x12345678 存放在内存地址0x0开始的连续四个字节中 (即地址0x0到 0x3). 那么在以Little Endian字节序存储的memory中,地址0x3的地方存放的字节是:
- 0x12
- 0x34
- 0x56
- 0x78
a) Little-Endian就是低位字节排放在内存的低地址端, 高位字节排放在内存的高地址端。
int foo(int x,int y) { if(x<=0||y<=0) return 1; return 3*foo(x-1,y/2); } cout<<foo(3,5)<<endl;答案:27。
int foo (int x,int y ) { if (x<=0││y<=0) return 1; return 3*foo(x-6,y/2); }答案:81。
int fun(unsigned int x) { int n=0; while((x+1)) { n++; x=x|(x+1); } return n; }分析:x&(x-1)统计1的个数,x|(x+1)统计0的个数。2014二进制中一共有23个0则返回值为23。
int a[5]={1,2,3,4,5}; int *ptr=(int*)(&a+1); printf("%d,%d",*(a+1),*(ptr-1));分析:数组名的值是一个指针常量,也就是数组第一个元素的地址。*(a+1)等同于a[1],*(a+1)=2。&a+1指向数组最后一个元素的下一个位置,故*(ptr-1)指向数组的最后一个元素。选B。
void func(char str_arg[100]) { cout<<sizeof(str_arg)<<endl; } int main(int argc,char* argv[]) { char str[]="Hello"; char *p=str; cout<<sizeof(str)<<endl; cout<<sizeof(p)<<endl; func("test"); return 0; }
- 5,5,8
- 6,6,4
- 6,8,4
- 6,8,8
- vector的插入操作不会导致迭代器失效
- map的插入操作不会导致迭代器失效
- vector的删除操作只会导致指向被删除元素及后面的迭代器失效
- map的删除操作只会导致指向被删除元素的迭代器失效
容器类型 | 插入 | 删除 |
list | 所有迭代器不失效 | 有且仅有被删除的节点的迭代器才失效 |
vector | 当 vector 的容量(不是size)不改变时, 只失效之后的迭代器, 否则全部失效 | 被删除节点之后的迭代器全部失效 |
map、set | 所有迭代器不失效 | 有且仅有被删除的节点的迭代器才失效 |
- int a[4][4];
- int **a;
- int **a[4]
- int (*a)[4];
A,二维数组,不符合
B,二级指针,也就是指针指向的内容也还是存放指针的,符合
C,二级指针数组,数组的内容是二级指针,不符合
D,数组指针,不符合
- C++已有的任何运算符都可以重载
- const对象只能调用const类型成员函数
- 构造函数和析构函数都可以是虚函数
- 函数重载返回值类型必须相同
B,const是常对象,也就是不改变成员变量的值,而成员函数中只有const函数可以确保不改变成员变量的值;
C,析构函数一般定义为虚函数,构造函数不能是虚函数;
D,重载只要求函数名相同,参数类型和个数不同,不要求返回值类型。
A、注册窗口类->创建窗口->显示窗口->更新窗口->消息循环
B、注册窗口类->创建窗口->更新窗口->显示窗口->消息循环
C、创建窗口->注册窗口类->更新窗口->显示窗口->消息循环
D、创建窗口->注册窗口类->显示窗口->更新窗口->消息循环分析:在屏幕上显示一个窗口的过程一般有以下步骤,这就是主程序的结构流程:
(1)得到应用程序的句柄(GetModuleHandle)。
(2)注册窗口类(RegisterClassEx)。在注册之前,要先填写RegisterClassEx的参数WNDCLASSEX结构。
(3)建立窗口(CreateWindowEx)。
(4)显示窗口(ShowWindows)。
(5)刷新窗口客户区(UpdateWindow)。
(6)进入无限的消息获取和处理的循环。首先获取消息(GetMessage),如果有消息到达,则将消息分派到回调函数处理(DispatchMessage),如果消息是WM_QUIT,则退出循环。
A、CreateFile
B、CreateSemaphore
C、CreateDC
D、CeateEvent
答案:C。内核对象主要要用来供系统和应用程序管理系统资源,像进程、线程、文件等。存取符号对象、事件对象、文件对象、作业对象、互斥对象、管道对象、等待计时器对象等都是内核对象。 除了内核对象外,也可以使用其他类型的对象,如菜单、窗口、鼠标光标、刷子和字体等。这些对象属于用户对象或图形设备接口(GDI)对象,而不是内核对象。
12、用户双击鼠标时产生的消息序列,下面正确的是()- WM_LBUTTONDOWN,WM_LBUTTONUP,WM_LBUTTONDOWN,WM_LBUTTONUP
- WM_LBUTTONDOWN,WM_LBUTTONUP,WM_LBUTTONUP,WM_LBUTTONDBLCLK
- WM_LBUTTONDOWN,WM_LBUTTONUP,WM_LBUTTONDOWN,WM_LBUTTONDBLCLK
- WM_LBUTTONDOWN,WM_LBUTTONUP,WM_LBUTTONDBLCLK,WM_LBUTTONUP
- 1),2)
- 1),3)
- 1)
- 以上都不正确
1.信号量 2.读写锁 3.互斥量 4.事件 5.临界区(Critical Section)
- 1,3,4,5
- 5
- 3,5
- 1,3,5
互斥锁( mutexlock ):
最常使用于线程同步的锁;标记用来保证在任一时刻,只能有一个线程访问该对象,同一线程多次加锁操作会造成死锁;临界区和互斥量都可用来实现此锁,通常情况下锁操作失败会将该线程睡眠等待锁释放时被唤醒
自旋锁(spinlock):
同样用来标记只能有一个线程访问该对象,在同一线程多次加锁操作会造成死锁;使用硬件提供的swap指令或test_and_set指令实现;同互斥锁不同的是在锁操作需要等待的时候并不是睡眠等待唤醒,而是循环检测保持者已经释放了锁,这样做的好处是节省了线程从睡眠状态到唤醒之间内核会产生的消耗,在加锁时间短暂的环境下这点会提高很大效率
读写锁(rwlock):
高级别锁,区分读和写,符合条件时允许多个线程访问对象。处于读锁操作时可以允许其他线程和本线程的读锁, 但不允许写锁, 处于写锁时则任何锁操作都会睡眠等待;常见的操作系统会在写锁等待时屏蔽后续的读锁操作以防写锁被无限孤立而等待,在操作系统不支持情况下可以用引用计数加写优先等待来用互斥锁实现。 读写锁适用于大量读少量写的环境,但由于其特殊的逻辑使得其效率相对普通的互斥锁和自旋锁要慢一个数量级;值得注意的一点是按POSIX标准 在线程申请读锁并未释放前本线程申请写锁是成功的,但运行后的逻辑结果是无法预测
递归锁(recursivelock):
严格上讲递归锁只是互斥锁的一个特例,同样只能有一个线程访问该对象,但允许同一个线程在未释放其拥有的锁时反复对该锁进行加锁操作; windows下的临界区默认是支持递归锁的,而linux下的互斥量则需要设置参数PTHREAD_MUTEX_RECURSIVE_NP,默认则是不支持。
postmessage发出消息后,将消息放到消息队列中,马上返回
sendmessage发出消息后,一直等到该消息执行完毕,才返回
用sendmessage给其他线程创建的窗口发送消息时,消息也会进消息队列
用2个函数只能给当前进程的窗口发送消息
可以在不同进程之间传递少量只读数据
只能通过sendmessage方式来发送该消息
只能在窗口过程函数中处理该消息
可以在消息队列或窗口过程函数中处理该消息
int WINAPI WinMain( HINSTANCE hInstance , // handle to current instance HINSTANCE hPrevInstance , // handle to previous instance LPSTR lpCmdLine , // command line int nCmdShow // show state );第一个参数 hInstance 表示该程序当前运行的实例的句柄,这是一个数值。
第二个参数 hPrevInstance 表示当前实例的前一个实例的句柄。
第三个参数 lpCmdLine 是一个以空终止的字符串,指定传递给应用程序的命令行参数。
第四个参数 nCmdShow 指定程序的窗口应该如何显示,例如最大化、最小化、隐藏等。
WM_MOUSEMOVE
WM_TIMER
WM_CHAR
WM_WINDOWPOSCHANGED
- [3,2,5,7,4,6,8]
- [2,3,5,7,4,6,8]
- [2,3,4,5,7,8,6]
- [2,3,4,5,6,7,8]
然后让最后一个节点放在堆顶,做向下调整工作,让剩下的数组依然满足最小堆。
删除0后用8填充0的位置,为[8,3,2,5,7,4,6]
然后8和其子节点3,2比较,结果2最小,将2和8交换,为:[2,3,8,5,7,4,6]
然后8的下标为2,其两个孩子节点下标分别为2*2+1=5,2*2+2=6
也就是4和6两个元素,经比较,4最小,将8与4交换,为[2,3,4,5,7,8,6]
这时候8已经没有孩子节点了,调整完成。答案选C。
int x(int n) { if(n<=3) return 1; else return x(n-2)+x(n-4)+1; }试问计算x(x(8))时需要计算()次x函数。
- F,H,C,D,P,A,M,Q,R,S,Y,X
- P,A,C,S,Q,D,F,X,R,H,M,Y
- A,D,C,R,F,Q,M,S,Y,P,H,X
- H,C,Q,P,A,M,S,R,D,F,X,Y
- O(logn),O(n)
- O(logn),O(nlogn)
- O(1),O(n)
- O(1),O(nlogn)
- 2和4
- 1和5
- 4和2
- 5和1
UID | 年龄 | 地区 | 学历 | 收入 | 用户是否使用调查产品 |
1 | 低 | 北方 | 博士 | 低 | 是 |
2 | 高 | 北方 | 本科 | 中 | 否 |
3 | 低 | 南方 | 本科 | 高 | 否 |
4 | 高 | 北方 | 研究生 | 中 | 是 |
请计算年龄,地区,学历,收入中对用户是否使用调查产品信息增益最大的属性(Log23≈0.63)
- 年龄
- 地区
- 学历
- 收入
- O(logn)
- O(n*logn)
- O(n)
- O(n^2)
正向最大匹配法
逆向最大匹配法
最少切分
条件随机场
第一类是基于语法和规则的分词法。其基本思想就是在分词的同时进行句法、语义分析, 利用句法信息和语义信息来进行词性标注, 以解决分词歧义现象。因为现有的语法知识、句法规则十分笼统、复杂, 基于语法和规则的分词法所能达到的精确度远远还不能令人满意, 目前这种分词系统还处在试验阶段。
第二类是机械式分词法(即基于词典)。机械分词的原理是将文档中的字符串与词典中的词条进行逐一匹配, 如果词典中找到某个字符串, 则匹配成功, 可以切分, 否则不予切分。基于词典的机械分词法, 实现简单, 实用性强, 但机械分词法的最大的缺点就是词典的完备性不能得到保证。据统计, 用一个含有70 000 个词的词典去切分含有15 000 个词的语料库, 仍然有30% 以上的词条没有被分出来, 也就是说有4500 个词没有在词典中登录。
第三类是基于统计的方法。基于统计的分词法的基本原理是根据字符串在语料库中出现的统计频率来决定其是否构成词。词是字的组合, 相邻的字同时出现的次数越多, 就越有可能构成一个词。因此字与字相邻共现的频率或概率能够较好的反映它们成为词的可信度。
最大匹配是指以词典为依据,取词典中最长单词为第一个次取字数量的扫描串,在词典中进行扫描,这是基于词典分词的方法
1).正向最大匹配法
2).逆向最大匹配法
3).最少切分法:使每一句中切出的词数最小,这也是基于词典分词的方法
条件随机场是一个基于统计的序列标记和分割的方法,属于基于统计的分词方法范畴。它定义了整个标签序列的联合概率,各状态是非独立的,彼此之间可以交互,因此可以更好地模拟现实世界的数据。答案选D。
特征灵活
速度快
可容纳较多上下文信息
全局最优
HMM模型是对转移概率和表现概率直接建模,统计共现概率。
MEMM模型是对转移概率和表现概率建立联合概率,统计时统计的是条件概率,但MEMM容易陷入局部最优,是因为MEMM只在局部做归一化。
RF模型中,统计了全局概率,在 做归一化时,考虑了数据在全局的分布,而不是仅仅在局部归一化,这样就解决了MEMM中的标记偏置(label bias)的问题。
CRF没有HMM那样严格的独立性假设条件,因而可以容纳任意的上下文信息。特征设计灵活。(与ME一样) ————与HMM比较
同时,由于CRF计算全局最优输出节点的条件概率,它还克服了最大熵马尔可夫模型标记偏置(Label-bias)的缺点。 --————与MEMM比较
CRF是在给定需要标记的观察序列的条件下,计算整个标记序列的联合概率分布,而不是在给定当前状态条件下,定义下一个状态的状态分布。
CRF需要训练的参数更多,与MEMM和HMM相比,它存在训练代价大、复杂度高的缺点。答案选B。
- 1/2,1/2
- 25/102,12/50
- 50/51,24/25
- 25/51,12/25
Accuracy:(TP+TN)/all
F-value:2*recall*precision/(recall+precision)
G-mean:sqrt(precision*recall)
AUC:曲线下面积
ID3算法要求特征必须离散化
信息增益可以用熵,而不是GINI系数来计算
选取信息增益最大的特征,作为树的根节点
ID3算法是一个二叉树模型
- 216
- 240
- 288
- 360
- 增加训练集量
- 减少神经网络隐藏层节点数
- 删除稀疏的特征 S
- SVM算法中使用高斯核/RBF核代替线性核
- a=5,b=3,c=6
- a=2,b=3,c=5
- a=7,b=3,c=3
- a=2,b=6,c=3
- 冒泡
- 选择
- 归并
- 快排
- 堆排序
搜狗2015C++工程师笔试题解题分析