2018-春,深信服筆試(待完善)
今天晚上接到筆試通知,感悟很深,自己學得不夠仔細,因為今天考完,試卷還沒出來,先記錄一些自己記得的題目。
因為是線上筆試,要開攝像頭,而我的辣雞筆記本攝像頭壞了,借了一個朋友的筆記本線上筆試,沒有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);
}