今天晚上接到笔试通知,感悟很深,自己学得不够仔细,因为今天考完,试卷还没出来,先记录一些自己记得的题目。
因为是在线笔试,要开摄像头,而我的辣鸡笔记本摄像头坏了,借了一个朋友的笔记本在线笔试,没有IDE,很痛苦,编程题没法调试,编写代码格式对齐也很难受,很久没用STL,方法也记不得几个。
然后是选择题,有多选和单选,做完很难受。
1、int型全局变量、局部变量、静态变量未初始化,它们的值是什么。
全局变量、静态变量未初始化,值默认为0,而局部变量未初始化使用则会报错。
2、struct与union的区别,以及字节对齐方式(我被这个坑过两次,很久没学忘记了)
a.在存储多个成员信息时,编译器会自动给struct第个成员分配存储空间,struct 可以存储多个成员信息,而Union每个成员会用同一个存储空间,只能存储最后一个成员的信息。
b.都是由多个不同的数据类型成员组成,但在任何同一时刻,Union只存放了一个被先选中的成员,而结构体的所有成员都存在。
c .对于Union的不同成员赋值,将会对其他成员重写,原来成员的值就不存在了,而对于struct 的不同成员赋值 是互不影响的。
d.复合数据类型,union,struct,class的对齐方式为成员中数据类型的size最大的成员的对齐方式
例如:
union test {
int a;
char b[13];
};
test a;
sizeof(a); //16 按union中sizeof(int)>sizeof(char),按int对齐
3、大小端
这个可以勉强算是跟着上面来,
大端模式:
是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;
小端模式:
是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。
通过使用一个十六进制的值,用指针去访问,就可以看出是否是大小端,或者利用union也可以。
如 int x=0X11112222,
用char *p=(char*)&x
,然后按十六进制输出printf("%x",*p);
,小端,就会输出22,大端则是11.
4、多线程
之前看过并发教程第一二章,后面放了,所以很多知识都忘了,打算重新写一篇文章记录线程与进程的一些学习记录,也好好的理解进程与线程的概念,经历过秋招到现在面试的几家(只去过两三家),面试官都会问操作系统,多线程什么的,这方面知识是我最欠缺的,所以打算好好补一下。
5、判断变量存放位置
变量在内存地址的分布为:堆-栈-代码区-全局静态-常量数据
同一区域的各变量按声明的顺序在内存的中依次由低到高分配空间(只有未赋值的全局变量是个例外)。
全局变量和静态变量如果不赋值,默认为0。 栈中的变量如果不赋值,则是一个随机的数据。
编译器会认为全局变量和静态变量是等同的,已初始化的全局变量和静态变量分配在一起,未初始化的全局变量和静态变量分配在另一起。
堆的地址生长方向是低地址向高地址,而栈是高地址向低地址。
6、c字符串
在选择题看到给char ch[4]
赋值“hell”
的时候,我感觉会报错,但是又很纠结,没试过这样赋值,因为“hell”
中含有’\0‘
,考完之后自己去试了一下,的确编译完成执行的时候会报错Stack around the variable 'ch' was corrupted.
,也就是在栈中分配ch的内存的时候,就分配了4字节,而我们赋值溢出了,所以stack就被破坏了。
二进制位反序:
这道题,看到的本来想法是,先用字符数组去存放求出的二进制数,然后倒着把值算出来,然而,在考试前几个小时,我在网上偶然看过这道题,再然而,我压根没记住那个算法是怎么设计的,我就大概记得是位运算,所以我特么把这个题给放了,一句代码都没写,我也不知道我那时候怎么想的,那时候在想用位运算去解出,而不是用我自己的想法去做。
我的代码:
unsigned int reverse(unsigned int num)
{
int ch[1000];
int index = 0;
while (num / 2 != 0) {
ch[index] = num % 2;
num /= 2;
index++;
}
ch[index] = 1;
ch[index + 1] = '\0';
int ret = 0;
for (int i = 0; i <= index; i++) {
ret += ch[i] * pow(2, index-i);
}
return ret;
}
别人的代码:
不懂二进制运算的话的确有些难度,其实也就是把num从二进制低位加到高位,ret通过左移把低位移动到高位。
unsigned int reverse(unsigned int num)
{
unsigned int ret = 0;
for (int i = 0; i < 32; i++, num /= 2)
ret = ret * 2 + num % 2;
return ret;
}
计算围棋的气:
这道题让我很难受,看到题就想到用BFS做,我的做法是写出一个point类,然后利用stack来实现BFS,但是由于没有IDE,我开始想着用不用STL的stack….因为我记不住这个函数,好像有pop和push来着,有这两个的确也就足够了,那么问题就来了,调试,没有IDE,在线编辑器只提供对错,我毫无办法。
解题思路,要先知道怎么才算是气,从某个棋子出发,如果遇到非同色棋子,或者是无棋子,那么这个位置有一个气。
于是就很简单了,利用stack先进后出,把初始的位置压入栈,然后扩展身边的节点,符合以上条件,就压栈,直到遍历到stack为空,也就是遍历了所有的节点,然后就把计数的数组值都加起来就可以。
调整最小堆:
这个题是看代码,填空,由于在没有IDE的时候,莫名其妙的发呆,浪费了很多时间,所以做到这没多少时间,就随便看了看代码,可能是因为着急,没看到函数的参数是什么意思,我自己之前也写过一个调整最小堆,我卡在了我自己的想法,没好好的分析题目代码的含义。
题目代码(已填充的):
static void heap_arrange(int arr[], int cur, int cnt) //调整为小顶堆
{
int heaptop_val = arr[cur]; //堆顶的值
while (cur < cnt) {
int left = 2 * cur + 1;
int right = 2 * cur + 2;
int min = -1;
int min_val = heaptop_val;//填空
if (left < cnt && arr[left] < min_val) { //检查是否比左节点大
min = left;
min_val = arr[left];
}
if (right < cnt && arr[right] < min_val) {//检查是否比右节点大
min = right;
}
if (min == -1)
break;
arr[cur] = arr[min]; //填空
cur = min;//填空
}
arr[cur] = heaptop_val;//填空
}
我自己之前实现的调整最小堆: //一对比代码写得很丑…哈哈…
void adjust_heap(vector<int>&ary, int n) {
if (n == 1) {
return;
}
int index = pow(2, n - 2)-1;
int len = ary.size() - 1;
for (int i = index; i <= 2*index; i++) {
int left = i * 2 + 1;
int right = i * 2 + 2;
if (left < len &&right<=len) {
int vleft = ary[left];
int vright = ary[right];
int min = ary[i];
if (vleft < min) {
min = vleft;
}
if (vright < min) {
min = vright;
}
int tmpindex = (min == vleft) ? left : -1;
if (tmpindex == -1) {
tmpindex = (min == vright) ? right : -1;
}
if (tmpindex == -1) {
tmpindex = i;
continue;
}
swap(ary[i], ary[tmpindex]);
}
else if ((i * 2 + 1) == len) {
if (ary[i * 2 + 1] < ary[i]) {
swap(ary[i * 2 + 1], ary[i]);
}
}
}
adjust_heap(ary, n - 1);
}