劍指Offer——大疆筆試題+知識點總結
情景回顧
- 時間:2016.9.23 12:00-14:00 19:00-21:00
- 地點:山東省網絡環境智能計算技術重點實驗室
- 事件:大疆筆試
- 注意事項:要有大局觀,該舍棄的還是要舍棄,不要在一道編程題上占用超過30分鍾的時間。當你思考了15分鍾,還沒有好的解決方式的時候,毅然舍棄!
總體來說,大疆的題目不算太難。尤其是編程題,思路很清晰,不涉及到太復雜的算法。只有第三題可能涉及到遞歸操作(軟肋)。其中第二題有關完全二叉樹的操作,只需要知道完全二叉樹的四個重要性質就對了,借助數學運算就可將問題解決。
- 性質1 在二叉樹的第i層上至多有2^(i-1)個節點(i>=1).
- 性質2 深度為k的二叉樹至多有(2^k)-1個節點(k>=1).
- 性質3 對任何一棵二叉樹T,若葉子節點數為m,度為2的節點數為n,則m=n+1.
- 性質4 具有n個節點的完全二叉樹的深度為log2n(向下取整)+1。
這幾次考試均涉及到了C++中計算結構體大小sizeof()問題。看完下面的內容,你就會明白了。
影響結構體的sizeof的因素:
1)不同的系統(如32位或16位系統):不同的系統下int等類型的長度是變化的,如對於16位系統,int的長度(字節為2,而在32位系統下,int的長度為4;因此如果結構體中有int等類型的成員,在不同的系統中得到的sizeof值是不相同的。
2)編譯器設置中的對齊方式:對齊方式的作用常常會讓我們對結構體的sizeof值感到驚訝。
對齊
為了能使CPU對變量進行高效快速的訪問,變量的起始地址應該具有某些特性,即所謂的“對齊”。例如對於4字節的int類型變量,其起始地址應位於4字節邊界上,即起始地址能夠被4整除。變量的對齊規則如下(32位系統):
請看下面的結構:
1 struct MyStruct 2 3 { 4 5 double dda1; 6 7 char dda; 8 9 int type; 10 11 };
對結構MyStruct采用sizeof會出現什么結果呢?sizeof(MyStruct)為多少呢?也許你會這樣求:
sizeof(MyStruct)=sizeof(double)+sizeof(char)+sizeof(int)=13
但是當在VC中測試上面結構的大小時,你會發現sizeof(MyStruct)為16。你知道為什么在VC中會得出這樣一個結果嗎?
其實,這是VC對變量存儲的一個特殊處理。為了提高CPU的存儲速度,VC對一些變量的起始地址做了”對齊”處理。在默認情況下,VC規定各成員變量存放的起始地址相對於結構的起始地址的偏移量必須為該變量的類型所占用的字節數的倍數。下面列出常用類型的對齊方式(vc6.0,32位系統)。
類型 對齊方式(變量存放的起始地址相對於結構的起始地址的偏移量)
char 偏移量必須為sizeof(char)即1的倍數
int 偏移量必須為sizeof(int)即4的倍數
float 偏移量必須為sizeof(float)即4的倍數
double 偏移量必須為sizeof(double)即8的倍數
short 偏移量必須為sizeof(short)即2的倍數
各成員變量在存放的時候根據在結構中出現的順序依次申請空間,同時按照上面的對齊方式調整位置,空缺的字節VC會自動填充。同時VC為了確保結構的大小為結 構的字節邊界數(即該結構中占用最大空間的類型所占用的字節數)的倍數,所以在為最后一個成員變量申請空間后,還會根據需要自動填充空缺的字節。
下面用前面的例子來說明VC到底怎么樣來存放結構的。
1 struct MyStruct 2 3 { 4 5 double dda1; 6 7 char dda; 8 9 int type; 10 11 };
為上面的結構分配空間的時候,VC根據成員變量出現的順序和對齊方式,先為第一個成員dda1分配空間,其起始地址跟結構的起始地址相同(剛好偏移量0剛好為sizeof(double)的倍數),該成員變量占用sizeof(double)=8個字節;接下來為第二個成員dda分配空間,這時下一個可以分配的地址對於結構的起始地址的偏移量為8,是sizeof(char)的倍數,所以把dda存放在偏移量為8的地方滿足對齊方式,該成員變量占用 sizeof(char)=1個字節;接下來為第三個成員type分配空間,這時下一個可以分配的地址對於結構的起始地址的偏移量為9(8+1),不是sizeof(int)=4的倍數,為了滿足對齊方式對偏移量的約束問題,VC自動填充3個字節(這三個字節沒有放什么東西),這時下一個可以分配的地址對於結構的起 始地址的偏移量為12(8+1+3),剛好是sizeof(int)=4的倍數,所以把type存放在偏移量為12的地方,該成員變量占sizeof(int)=4個 字節;這時整個結構的成員變量已經都分配了空間,總的占用的空間大小為:8 1 3 4=16,剛好為結構的字節邊界數(即結構中占用最大空間的類型所占用的字節sizeof(double)=8)的倍數,所以沒有空缺的字節需要填充。所以整個結構的大小為:sizeof(MyStruct)=8+1+3+4=16,其中有3個字節是VC自動填充的,沒有放任何有意義的東西。
下面再舉個例子,交換一下上面的MyStruct的成員變量的位置,使它變成下面的情況:
1 struct MyStruct 2 3 { 4 5 char dda; 6 7 double dda1; 8 9 int type; 10 11 };
這個結構占用的空間為多大呢?在VC6.0環境下,可以得到sizeof(MyStruc)為24。結合上面提到的分配空間的一些原則,分析下VC怎么樣為上面的結構分配空間的。(簡單說明)
struct MyStruct
{
char dda; //偏移量為0,滿足對齊方式,dda占用1個字節;
double dda1; //下一個可用的地址的偏移量為1,不是sizeof(double)=8的倍數,需要補足7個字節才能使偏移量變為8(滿足對齊方式),因此VC自動填充7個字節,dda1存放在偏移量為8的地址上,它占用8個字節。
int type;//下一個可用的地址的偏移量為16,是sizeof(int)=4的倍數,滿足int的對齊方式,所以不需要VC自動填充,type存放在偏移量為16的地址上,它占用4個字節。
}; //所有成員變量都分配了空間,空間總的大小為1+7+8+4=20,不是結構的節邊界數(即結構中占用最大空間的類型所占用的字節數sizeof (double)=8)的倍數,所以需要填充4個字節,以滿足結構的大小為sizeof(double)=8的倍數。
所以該結構總的大小為:sizeof(MyStruc)為1+7+8+4+4=24。其中總的有7+4=11個字節是VC自動填充的,沒有放任何有意義的東西。
new與malloc的區別
參考網址:
http://blog.csdn.net/miss_acha/article/details/7279915
http://www.cnblogs.com/huhuuu/archive/2013/11/19/3432371.html
計算十六進制表示形式中1的個數
PS:唉,做錯了,多加了1。對於較大的數,自己應該首先用簡單的數驗證一下的,而不至於算錯!

package cn.edu.ujn.offersword; import java.util.Scanner; public class C2_10_NumberOf1InBinary { /** * * 二進制中1的個數 * * 題目描述 輸入一個整數,輸出該數二進制表示中1的個數。其中負數用補碼表示。 * * @author SHQ */ public static void main(String[] args) { Scanner in = new Scanner(System.in); while(in.hasNext()){ int n = in.nextInt(); System.out.println(NumberOf1(n)); } } // n 中有多少個1就循環多少次 private static int NumberOf1(int n){ int cnt = 0; while(n != 0){ ++cnt; n = (n - 1) & n; } return cnt; } // n 中有多少位二進制就循環多少次 private static int NumberOf1_(int n){ int cnt = 0; int flag = 1; while(flag != 0){ if((n & (flag)) != 0) cnt++; flag = flag << 1; } return cnt; } }
解決hash沖突的方法
與DES、AES加密方式相比,RSA、ECC加密方式屬於非對稱加密(答對)?
參考文獻:http://www.willrey.com/support/ssl_DES.html
BigEndian形式為 43981,16進制無符號數占2個字節,存儲在LittleEndian中的形式為_____?
參考
Big Endian 10110100
Little Endian 00101101
實際上,由於CPU存儲數據操作的最小單位是一個字節,其內部的比特序是什么樣對我們的程序來說是一個黑盒子。也就是說,你給我一個指向0xB4這個數的指針,對於big endian方式的CPU來說,它是從左往右依次讀取這個數的8個比特;而對於little endian方式的CPU來說,則正好相反,是從右往左依次讀取這個數的8個比特。而我們的程序通過這個指針訪問后得到的數就是0xB4,字節內部的比特序對於程序來說是不可見的,其實這點對於單機上的字節序來說也是一樣的。
那可能有人又會問,如果是網絡傳輸呢?會不會出問題?是不是也要通過什么函數轉換一下比特序?嗯,這個問題提得很好。假設little endian方式的CPU要傳給big endian方式CPU一個字節的話,其本身在傳輸之前會在本地就讀出這個8比特的數,然后再按照網絡字節序的順序來傳輸這8個比特,這樣的話到了接收端不會出現任何問題。而假如要傳輸一個32比特的數的話,由於這個數在littel endian方存儲時占了4個字節,而網絡傳輸是以字節為單位進行的,little endian方的CPU讀出第一個字節后發送,實際上這個字節是原數的LSB,到了接收方反倒成了MSB從而發生混亂。
大疆編程題
1.有關矩陣的操作,子矩陣增值與查詢其和。
2.考察完全二叉樹,給出完全二叉樹的頂點數,求出其深度與葉子節點的數目。
3.長度為n的方格,刷3種顏色的顏料,相鄰的方格顏料顏色不能相同,且首尾方格顏色不能相同。每個方格必須塗色。計算一共有多少種塗色方式。
4.問答題 集群網關分發請求至處理服務器的方法及其優缺點。
實際上考察集群負載均衡策略。